Merge "Fix MonkeyApp so it keeps the current screen orientation on TVs" into lmp-sprout-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 80e1efc..7c032d7 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -70,9 +70,12 @@
     CtsDeviceUi \
     CtsIntentReceiverApp \
     CtsIntentSenderApp \
+    CtsLauncherAppsTests \
+    CtsLauncherAppsTestsSupport \
     CtsManagedProfileApp \
     CtsMonkeyApp \
     CtsMonkeyApp2 \
+    CtsSimpleApp \
     CtsSomeAccessibilityServices \
     CtsThemeDeviceApp \
     TestDeviceSetup \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 1afa9af..41ee319 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1114,6 +1114,10 @@
             <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
             <meta-data android:name="test_excluded_features"
                     android:value="android.hardware.type.watch" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
         </activity>
 
         <service android:name=".notifications.MockListener"
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
new file mode 100644
index 0000000..4517ea2
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
@@ -0,0 +1,31 @@
+# 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 := CtsLauncherAppsTests
+
+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 cts-junit
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/AndroidManifest.xml b/hostsidetests/devicepolicy/app/LauncherTests/AndroidManifest.xml
new file mode 100644
index 0000000..a21b8c2
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/LauncherTests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.launchertests">
+
+    <uses-sdk android:minSdkVersion="21"/>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.cts.launchertests"
+                     android:label="Launcher Apps CTS Tests"/>
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java b/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java
new file mode 100644
index 0000000..3d44ecd
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java
@@ -0,0 +1,287 @@
+/*
+ * 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.launchertests;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.test.InstrumentationTestCase;
+import android.test.InstrumentationTestRunner;
+import android.util.Pair;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.List;
+
+/**
+ * Tests for LauncherApps service
+ */
+public class LauncherAppsTests extends InstrumentationTestCase {
+
+    public static final String SIMPLE_APP_PACKAGE = "com.android.cts.launcherapps.simpleapp";
+
+    public static final String USER_EXTRA = "user_extra";
+    public static final String PACKAGE_EXTRA = "package_extra";
+    public static final String REPLY_EXTRA = "reply_extra";
+
+    public static final int MSG_RESULT = 0;
+    public static final int MSG_CHECK_PACKAGE_ADDED = 1;
+    public static final int MSG_CHECK_PACKAGE_REMOVED = 2;
+    public static final int MSG_CHECK_PACKAGE_CHANGED = 3;
+    public static final int MSG_CHECK_NO_CALLBACK = 4;
+
+    public static final int RESULT_PASS = 1;
+    public static final int RESULT_FAIL = 2;
+    public static final int RESULT_TIMEOUT = 3;
+
+    private LauncherApps mLauncherApps;
+    private UserHandle mUser;
+    private InstrumentationTestRunner mInstrumentation;
+    private Messenger mService;
+    private Connection mConnection;
+    private Result mResult;
+    private Messenger mResultMessenger;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mInstrumentation = (InstrumentationTestRunner) getInstrumentation();
+        Bundle arguments = mInstrumentation.getArguments();
+        UserManager userManager = (UserManager) mInstrumentation.getContext().getSystemService(
+                Context.USER_SERVICE);
+        mUser = getUserHandleArgument(userManager, "testUser", arguments);
+        mLauncherApps = (LauncherApps) mInstrumentation.getContext().getSystemService(
+                Context.LAUNCHER_APPS_SERVICE);
+
+        final Intent intent = new Intent();
+        intent.setComponent(new ComponentName("com.android.cts.launchertests.support",
+                        "com.android.cts.launchertests.support.LauncherCallbackTestsService"));
+
+        mConnection = new Connection();
+        mInstrumentation.getContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+        mConnection.waitForService();
+        mResult = new Result(Looper.getMainLooper());
+        mResultMessenger = new Messenger(mResult);
+    }
+
+    public void testGetActivitiesForUserFails() throws Exception {
+        try {
+            List<LauncherActivityInfo> activities =
+                    mLauncherApps.getActivityList(null, mUser);
+            fail("getActivities for non-profile user failed to throw exception");
+        } catch (SecurityException e) {
+            // Expected.
+        }
+    }
+
+    public void testSimpleAppInstalledForUser() throws Exception {
+        List<LauncherActivityInfo> activities =
+                mLauncherApps.getActivityList(null, mUser);
+        // Check simple app is there.
+        boolean foundSimpleApp = false;
+        for (LauncherActivityInfo activity : activities) {
+            if (activity.getComponentName().getPackageName().equals(
+                    SIMPLE_APP_PACKAGE)) {
+                foundSimpleApp = true;
+            }
+            assertTrue(activity.getUser().equals(mUser));
+        }
+        assertTrue(foundSimpleApp);
+    }
+
+    public void testPackageAddedCallbackForUser() throws Throwable {
+        int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_ADDED,
+                mUser, SIMPLE_APP_PACKAGE);
+        assertEquals(RESULT_PASS, result);
+    }
+
+    public void testPackageRemovedCallbackForUser() throws Throwable {
+        int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_REMOVED,
+                mUser, SIMPLE_APP_PACKAGE);
+        assertEquals(RESULT_PASS, result);
+    }
+    public void testPackageChangedCallbackForUser() throws Throwable {
+        int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_CHANGED,
+                mUser, SIMPLE_APP_PACKAGE);
+        assertEquals(RESULT_PASS, result);
+    }
+
+    public void testNoCallbackForUser() throws Throwable {
+        int result = sendMessageToCallbacksService(MSG_CHECK_NO_CALLBACK,
+                mUser, SIMPLE_APP_PACKAGE);
+        assertEquals(RESULT_PASS, result);
+    }
+
+    public void testLaunchNonExportActivityFails() throws Exception {
+        try {
+            mLauncherApps.startMainActivity(new ComponentName(
+                    SIMPLE_APP_PACKAGE,
+                    SIMPLE_APP_PACKAGE + ".NonExportedActivity"),
+                    mUser, null, null);
+            fail("starting non-exported activity failed to throw exception");
+        } catch (SecurityException e) {
+            // Expected.
+        }
+    }
+
+    public void testLaunchNonExportLauncherFails() throws Exception {
+        try {
+            mLauncherApps.startMainActivity(new ComponentName(
+                    SIMPLE_APP_PACKAGE,
+                    SIMPLE_APP_PACKAGE + ".NonLauncherActivity"),
+                    mUser, null, null);
+            fail("starting non-launcher activity failed to throw exception");
+        } catch (SecurityException e) {
+            // Expected.
+        }
+    }
+
+    public void testLaunchMainActivity() throws Exception {
+        ActivityLaunchedReceiver receiver = new ActivityLaunchedReceiver();
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ActivityLaunchedReceiver.ACTIVITY_LAUNCHED_ACTION);
+        mInstrumentation.getContext().registerReceiver(receiver, filter);
+        mLauncherApps.startMainActivity(new ComponentName(
+                SIMPLE_APP_PACKAGE,
+                SIMPLE_APP_PACKAGE + ".SimpleActivity"),
+                mUser, null, null);
+        assertEquals(RESULT_PASS, receiver.waitForActivity());
+        mInstrumentation.getContext().unregisterReceiver(receiver);
+    }
+
+    private UserHandle getUserHandleArgument(UserManager userManager, String key,
+            Bundle arguments) throws Exception {
+        String serial = arguments.getString(key);
+        if (serial == null) {
+            return null;
+        }
+        int serialNo = Integer.parseInt(serial);
+        return userManager.getUserForSerialNumber(serialNo);
+    }
+
+    private class Connection implements ServiceConnection {
+        private final Semaphore mSemaphore = new Semaphore(0);
+
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            mService = new Messenger(service);
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            mService = null;
+        }
+
+        public void waitForService() {
+            try {
+                if (mSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
+                    return;
+                }
+            } catch (InterruptedException e) {
+            }
+            fail("failed to connec to service");
+        }
+    };
+
+    private static class Result extends Handler {
+
+        private final Semaphore mSemaphore = new Semaphore(0);
+        public int result = 0;
+
+        public Result(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what == MSG_RESULT) {
+                result = msg.arg1;
+                mSemaphore.release();
+            } else {
+                super.handleMessage(msg);
+            }
+        }
+
+        public int waitForResult() {
+            try {
+                if (mSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
+                    return result;
+                }
+            } catch (InterruptedException e) {
+            }
+            return RESULT_TIMEOUT;
+        }
+    }
+
+    public class ActivityLaunchedReceiver extends BroadcastReceiver {
+        public static final String ACTIVITY_LAUNCHED_ACTION =
+                "com.android.cts.launchertests.LauncherAppsTests.LAUNCHED_ACTION";
+
+        private final Semaphore mSemaphore = new Semaphore(0);
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(ACTIVITY_LAUNCHED_ACTION)) {
+                mSemaphore.release();
+            }
+        }
+
+        public int waitForActivity() {
+            try {
+                if (mSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
+                    return RESULT_PASS;
+                }
+            } catch (InterruptedException e) {
+            }
+            return RESULT_TIMEOUT;
+        }
+    }
+
+    private int sendMessageToCallbacksService(int msg, UserHandle user, String packageName)
+            throws Throwable {
+        Bundle params = new Bundle();
+        params.putParcelable(USER_EXTRA, user);
+        params.putString(PACKAGE_EXTRA, packageName);
+
+        Message message = Message.obtain(null, msg, params);
+        message.replyTo = mResultMessenger;
+
+        mService.send(message);
+
+        return mResult.waitForResult();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/TestActivity.java b/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/TestActivity.java
new file mode 100644
index 0000000..5d62c8f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/TestActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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.launchertests;
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.lang.Override;
+
+/**
+ * A simple activity to install and launch for various users to
+ * test LauncherApps.
+ */
+public class TestActivity extends Activity {
+    public static final String USER_EXTRA = "user_extra";
+    public static final int MSG_RESULT = 0;
+    public static final int RESULT_PASS = 1;
+
+    private static final String TAG = "SimpleActivity";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        Log.i(TAG, "Created for user " + android.os.Process.myUserHandle());
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/LauncherTestsSupport/Android.mk b/hostsidetests/devicepolicy/app/LauncherTestsSupport/Android.mk
new file mode 100644
index 0000000..2465ef3
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/LauncherTestsSupport/Android.mk
@@ -0,0 +1,31 @@
+# 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 := CtsLauncherAppsTestsSupport
+
+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 cts-junit
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/LauncherTestsSupport/AndroidManifest.xml b/hostsidetests/devicepolicy/app/LauncherTestsSupport/AndroidManifest.xml
new file mode 100644
index 0000000..fbd049f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/LauncherTestsSupport/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.launchertests.support">
+
+    <uses-sdk android:minSdkVersion="21"/>
+
+    <application>
+        <service android:name=".LauncherCallbackTestsService" >
+            <intent-filter>
+                <action android:name="com.android.cts.launchertests.support.REGISTER_CALLBACK" />
+            </intent-filter>
+        </service>
+    </application>
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/LauncherTestsSupport/src/com/android/cts/launchertests/support/LauncherCallbackTestsService.java b/hostsidetests/devicepolicy/app/LauncherTestsSupport/src/com/android/cts/launchertests/support/LauncherCallbackTestsService.java
new file mode 100644
index 0000000..8d61496
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/LauncherTestsSupport/src/com/android/cts/launchertests/support/LauncherCallbackTestsService.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2014 The Android Open Sour *
+ * 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.launchertests.support;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Service that registers for LauncherApps callbacks.
+ *
+ * Registering in a service and different process so that
+ * device side code can launch it before running client
+ * side test code.
+ */
+public class LauncherCallbackTestsService extends Service {
+
+    public static final String USER_EXTRA = "user_extra";
+    public static final String PACKAGE_EXTRA = "package_extra";
+
+    public static final int MSG_RESULT = 0;
+    public static final int MSG_CHECK_PACKAGE_ADDED = 1;
+    public static final int MSG_CHECK_PACKAGE_REMOVED = 2;
+    public static final int MSG_CHECK_PACKAGE_CHANGED = 3;
+    public static final int MSG_CHECK_NO_CALLBACK = 4;
+
+    public static final int RESULT_PASS = 1;
+    public static final int RESULT_FAIL = 2;
+
+    private static final String TAG = "LauncherCallbackTests";
+
+    private static List<Pair<String, UserHandle>> mPackagesAdded
+            = new ArrayList<Pair<String, UserHandle>>();
+    private static List<Pair<String, UserHandle>> mPackagesRemoved
+            = new ArrayList<Pair<String, UserHandle>>();
+    private static List<Pair<String, UserHandle>> mPackagesChanged
+            = new ArrayList<Pair<String, UserHandle>>();
+    private static Object mPackagesLock = new Object();
+
+    private TestCallback mCallback;
+    private final Messenger mMessenger = new Messenger(new CheckHandler());
+
+    class CheckHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            Bundle params = null;
+            if (msg.obj instanceof Bundle) {
+                params = (Bundle) (msg.obj);
+            }
+            try {
+                switch (msg.what) {
+                    case MSG_CHECK_PACKAGE_ADDED: {
+                        boolean exists = eventExists(params, mPackagesAdded);
+                        teardown();
+                        msg.replyTo.send(Message.obtain(null, MSG_RESULT,
+                                        exists ? RESULT_PASS : RESULT_FAIL, 0));
+                        break;
+                    }
+                    case MSG_CHECK_PACKAGE_REMOVED: {
+                        boolean exists = eventExists(params, mPackagesRemoved);
+                        teardown();
+                        msg.replyTo.send(Message.obtain(null, MSG_RESULT,
+                                        exists ? RESULT_PASS : RESULT_FAIL, 0));
+                        break;
+                    }
+                    case MSG_CHECK_PACKAGE_CHANGED: {
+                        boolean exists = eventExists(params, mPackagesChanged);
+                        teardown();
+                        msg.replyTo.send(Message.obtain(null, MSG_RESULT,
+                                        exists ? RESULT_PASS : RESULT_FAIL, 0));
+                        break;
+                    }
+                    case MSG_CHECK_NO_CALLBACK: {
+                        boolean exists = eventExists(params, mPackagesAdded)
+                                || eventExists(params, mPackagesRemoved)
+                                || eventExists(params, mPackagesChanged);
+                        teardown();
+                        msg.replyTo.send(Message.obtain(null, MSG_RESULT,
+                                        exists ? RESULT_FAIL : RESULT_PASS, 0));
+                        break;
+                    }
+                    default:
+                        super.handleMessage(msg);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to report test status");
+            }
+        }
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (intent == null) {
+            return START_NOT_STICKY;
+        }
+        if ("com.android.cts.launchertests.support.REGISTER_CALLBACK".equals(intent.getAction())) {
+            setup();
+        }
+        return START_STICKY;
+    }
+
+    private void setup() {
+        LauncherApps launcherApps = (LauncherApps) getSystemService(
+                Context.LAUNCHER_APPS_SERVICE);
+        synchronized (mPackagesLock) {
+            mPackagesAdded.clear();
+            mPackagesRemoved.clear();
+            mPackagesChanged.clear();
+            if (mCallback != null) {
+                launcherApps.unregisterCallback(mCallback);
+            }
+            mCallback = new TestCallback();
+            launcherApps.registerCallback(mCallback);
+        }
+    }
+
+    private void teardown() {
+        LauncherApps launcherApps = (LauncherApps) getSystemService(
+                Context.LAUNCHER_APPS_SERVICE);
+        synchronized (mPackagesLock) {
+            if (mCallback != null) {
+                launcherApps.unregisterCallback(mCallback);
+                mCallback = null;
+            }
+            mPackagesAdded.clear();
+            mPackagesRemoved.clear();
+            mPackagesChanged.clear();
+        }
+    }
+
+    private boolean eventExists(Bundle params, List<Pair<String, UserHandle>> events) {
+        UserHandle user = params.getParcelable(USER_EXTRA);
+        String packageName = params.getString(PACKAGE_EXTRA);
+        synchronized (mPackagesLock) {
+            if (events != null) {
+                for (Pair<String, UserHandle> added : events) {
+                    if (added.first.equals(packageName) && added.second.equals(user)) {
+                        Log.i(TAG, "Event exists " + packageName + " for user " + user);
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mMessenger.getBinder();
+    }
+
+    private class TestCallback extends LauncherApps.Callback {
+        public void onPackageRemoved(String packageName, UserHandle user) {
+            synchronized (mPackagesLock) {
+                mPackagesRemoved.add(new Pair<String, UserHandle>(packageName, user));
+            }
+        }
+
+        public void onPackageAdded(String packageName, UserHandle user) {
+            synchronized (mPackagesLock) {
+                mPackagesAdded.add(new Pair<String, UserHandle>(packageName, user));
+            }
+        }
+
+        public void onPackageChanged(String packageName, UserHandle user) {
+            synchronized (mPackagesLock) {
+                mPackagesChanged.add(new Pair<String, UserHandle>(packageName, user));
+            }
+        }
+
+        public void onPackagesAvailable(String[] packageNames, UserHandle user,
+                boolean replacing) {
+        }
+
+        public void onPackagesUnavailable(String[] packageNames, UserHandle user,
+                boolean replacing) {
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/Android.mk b/hostsidetests/devicepolicy/app/SimpleApp/Android.mk
new file mode 100644
index 0000000..eae0a4f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SimpleApp/Android.mk
@@ -0,0 +1,31 @@
+# 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)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSimpleApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml b/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml
new file mode 100644
index 0000000..848317c
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?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.launcherapps.simpleapp">
+
+    <application>
+        <activity android:name=".SimpleActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".NonExportedActivity">
+            android:exported="false">
+        </activity>
+        <activity android:name=".NonLauncherActivity">
+            android:exported="true">
+        </activity>
+    </application>
+
+</manifest>
+
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/NonExportedActivity.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/NonExportedActivity.java
new file mode 100644
index 0000000..4801830
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/NonExportedActivity.java
@@ -0,0 +1,38 @@
+/*
+ * 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.launcherapps.simpleapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.lang.Override;
+
+/**
+ * A simple activity that isn't exported, shouldn't be launchable
+ * by LauncherApps.
+ */
+public class NonExportedActivity extends Activity {
+
+    private static final String TAG = "NonExportedActivity";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        Log.i(TAG, "Created for user " + android.os.Process.myUserHandle());
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/NonLauncherActivity.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/NonLauncherActivity.java
new file mode 100644
index 0000000..4809020
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/NonLauncherActivity.java
@@ -0,0 +1,38 @@
+/*
+ * 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.launcherapps.simpleapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.lang.Override;
+
+/**
+ * A simple activity that isn't main / category launcher, shouldn't be launchable
+ * by LauncherApps.
+ */
+public class NonLauncherActivity extends Activity {
+
+    private static final String TAG = "NonLauncherActivity";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        Log.i(TAG, "Created for user " + android.os.Process.myUserHandle());
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java
new file mode 100644
index 0000000..1d30335
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java
@@ -0,0 +1,47 @@
+/*
+ * 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.launcherapps.simpleapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.lang.Override;
+
+/**
+ * A simple activity to install for various users to test LauncherApps.
+ */
+public class SimpleActivity extends Activity {
+    public static String ACTIVITY_LAUNCHED_ACTION =
+            "com.android.cts.launchertests.LauncherAppsTests.LAUNCHED_ACTION";
+
+    private static final String TAG = "SimpleActivity";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        Log.i(TAG, "Created for user " + android.os.Process.myUserHandle());
+    }
+
+    public void onStart() {
+        super.onStart();
+        Intent reply = new Intent();
+        reply.setAction(ACTIVITY_LAUNCHED_ACTION);
+        sendBroadcast(reply);
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 544ddff..baaa14c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -47,6 +47,11 @@
  */
 public class BaseDevicePolicyTest extends DeviceTestCase implements IBuildReceiver {
 
+    protected static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
+    protected static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
+    protected static final String ADMIN_RECEIVER_TEST_CLASS =
+            MANAGED_PROFILE_PKG + ".BaseManagedProfileTest$BasicAdminReceiver";
+
     private static final String RUNNER = "android.test.InstrumentationTestRunner";
 
     private static final String[] REQUIRED_DEVICE_FEATURES = new String[] {
@@ -72,6 +77,7 @@
 
     protected void installApp(String fileName)
             throws FileNotFoundException, DeviceNotAvailableException {
+        CLog.logAndDisplay(LogLevel.INFO, "Installing app " + fileName);
         String installResult = getDevice().installPackage(mCtsBuild.getTestApp(fileName), true);
         assertNull(String.format("Failed to install %s, Reason: %s", fileName, installResult),
                 installResult);
@@ -93,12 +99,15 @@
     }
 
     /** Initializes the user with the given id. This is required so that apps can run on it. */
-    protected void startUser(int userId) throws DeviceNotAvailableException {
+    protected void startUser(int userId) throws Exception {
         String command = "am start-user " + userId;
+        CLog.logAndDisplay(LogLevel.INFO, "Starting command " + command);
         String commandOutput = getDevice().executeShellCommand(command);
         CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
         assertTrue(commandOutput + " expected to start with \"Success:\"",
                 commandOutput.startsWith("Success:"));
+        // Wait 60 seconds for intents generated to be handled.
+        Thread.sleep(60 * 1000);
     }
 
     protected int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException {
@@ -137,10 +146,13 @@
         return users;
     }
 
-    protected void removeUser(int userId) throws DeviceNotAvailableException  {
+    protected void removeUser(int userId) throws Exception  {
         String removeUserCommand = "pm remove-user " + userId;
+        CLog.logAndDisplay(LogLevel.INFO, "starting command " + removeUserCommand);
         CLog.logAndDisplay(LogLevel.INFO, "Output for command " + removeUserCommand + ": "
                 + getDevice().executeShellCommand(removeUserCommand));
+        // Wait 60 seconds for user to finish being removed.
+        Thread.sleep(60 * 1000);
     }
 
     /** Returns true if the specified tests passed. Tests are run as user owner. */
@@ -166,12 +178,19 @@
         return runDeviceTests(pkgName, testClassName, testMethodName, userId);
     }
 
-    private boolean runDeviceTests(String pkgName, @Nullable String testClassName,
+    protected boolean runDeviceTests(String pkgName, @Nullable String testClassName,
             @Nullable String testMethodName, @Nullable Integer userId)
-                    throws DeviceNotAvailableException {
-        TestRunResult runResult = (userId == null)
+            throws DeviceNotAvailableException {
+        return runDeviceTests(pkgName, testClassName, testMethodName, userId, /*params*/ null);
+    }
+
+    protected boolean runDeviceTests(String pkgName, @Nullable String testClassName,
+            @Nullable String testMethodName, @Nullable Integer userId, @Nullable String params)
+                   throws DeviceNotAvailableException {
+        TestRunResult runResult = (userId == null && params == null)
                 ? doRunTests(pkgName, testClassName, testMethodName)
-                : doRunTestsAsUser(pkgName, testClassName, testMethodName, userId);
+                : doRunTestsAsUser(pkgName, testClassName, testMethodName,
+                        userId != null ? userId : 0, params != null ? params : "");
         printTestResult(runResult);
         return !runResult.hasFailedTests() && runResult.getNumTestsInState(TestStatus.PASSED) > 0;
     }
@@ -194,7 +213,7 @@
     }
 
     private TestRunResult doRunTestsAsUser(String pkgName, @Nullable String testClassName,
-            @Nullable String testMethodName, int userId)
+            @Nullable String testMethodName, int userId, String params)
             throws DeviceNotAvailableException {
         // TODO: move this to RemoteAndroidTestRunner once it supports users. Should be straight
         // forward to add a RemoteAndroidTestRunner.setUser(userId) method. Then we can merge both
@@ -206,8 +225,8 @@
                 testsToRun.append("#" + testMethodName);
             }
         }
-        String command = "am instrument --user " + userId + " -w -r " + testsToRun + " "
-                + pkgName + "/" + RUNNER;
+        String command = "am instrument --user " + userId + " " + params + " -w -r "
+                + testsToRun + " " + pkgName + "/" + RUNNER;
         CLog.i("Running " + command);
 
         CollectingTestListener listener = new CollectingTestListener();
@@ -255,4 +274,63 @@
         }
         return true;
     }
+
+    protected int createUser() throws Exception {
+        String command ="pm create-user TestUser_"+ System.currentTimeMillis();
+        CLog.logAndDisplay(LogLevel.INFO, "Starting command " + command);
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+
+        // Extract the id of the new user.
+        String[] tokens = commandOutput.split("\\s+");
+        assertTrue(tokens.length > 0);
+        assertEquals("Success:", tokens[0]);
+        // Wait 60 seconds for intents generated to be handled.
+        Thread.sleep(60 * 1000);
+        return Integer.parseInt(tokens[tokens.length-1]);
+    }
+
+    protected int createManagedProfile() throws DeviceNotAvailableException {
+        String command =
+                "pm create-user --profileOf 0 --managed TestProfile_" + System.currentTimeMillis();
+        CLog.logAndDisplay(LogLevel.INFO, "Starting command " + command);
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+
+        // Extract the id of the new user.
+        String[] tokens = commandOutput.split("\\s+");
+        assertTrue(commandOutput + " expected to have format \"Success: {USER_ID}\"",
+                tokens.length > 0);
+        assertEquals(commandOutput, "Success:", tokens[0]);
+        return Integer.parseInt(tokens[tokens.length-1]);
+    }
+
+
+    protected int getUserSerialNumber(int userId) throws DeviceNotAvailableException{
+        // dumpsys user return lines like "UserInfo{0:Owner:13} serialNo=0"
+        String commandOutput = getDevice().executeShellCommand("dumpsys user");
+        String[] tokens = commandOutput.split("\\n");
+        for (String token : tokens) {
+            token = token.trim();
+            if (token.contains("UserInfo{" + userId + ":")) {
+                String[] split = token.split("serialNo=");
+                assertTrue(split.length == 2);
+                int serialNumber = Integer.parseInt(split[1]);
+                CLog.logAndDisplay(LogLevel.INFO, "Serial number of user " + userId + ": "
+                        + serialNumber);
+                return serialNumber;
+            }
+        }
+        fail("Couldn't find user " + userId);
+        return -1;
+    }
+
+    protected void setProfileOwner(String componentName, int userId)
+            throws DeviceNotAvailableException {
+        String command = "dpm set-profile-owner '" + componentName + "' " + userId;
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+        assertTrue(commandOutput + " expected to start with \"Success:\"",
+                commandOutput.startsWith("Success:"));
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseLauncherAppsTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseLauncherAppsTest.java
new file mode 100644
index 0000000..dec8bd2
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseLauncherAppsTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 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.devicepolicy;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
+/**
+ * Common code for the various LauncherApps tests.
+ */
+public class BaseLauncherAppsTest extends BaseDevicePolicyTest {
+
+    protected static final String SIMPLE_APP_PKG = "com.android.cts.launcherapps.simpleapp";
+    protected static final String SIMPLE_APP_APK = "CtsSimpleApp.apk";
+    protected static final String LAUNCHER_TESTS_PKG = "com.android.cts.launchertests";
+    protected static final String LAUNCHER_TESTS_CLASS = LAUNCHER_TESTS_PKG + ".LauncherAppsTests";
+    private static final String LAUNCHER_TESTS_APK = "CtsLauncherAppsTests.apk";
+    private static final String LAUNCHER_TESTS_SUPPORT_PKG =
+            "com.android.cts.launchertests.support";
+    private static final String LAUNCHER_TESTS_SUPPORT_APK = "CtsLauncherAppsTestsSupport.apk";
+
+    protected void installTestApps() throws Exception {
+        uninstallTestApps();
+        installApp(LAUNCHER_TESTS_APK);
+        installApp(LAUNCHER_TESTS_SUPPORT_APK);
+    }
+
+    protected void uninstallTestApps() throws Exception {
+        getDevice().uninstallPackage(LAUNCHER_TESTS_PKG);
+        getDevice().uninstallPackage(LAUNCHER_TESTS_SUPPORT_PKG);
+        getDevice().uninstallPackage(SIMPLE_APP_PKG);
+    }
+
+    protected void removeTestUsers() throws Exception {
+        for (int userId : listUsers()) {
+            if (userId != 0) {
+                removeUser(userId);
+            }
+        }
+    }
+
+    protected void startCallbackService() throws Exception {
+        String command = "am startservice --user 0 "
+                + "-a " + LAUNCHER_TESTS_SUPPORT_PKG + ".REGISTER_CALLBACK "
+                + LAUNCHER_TESTS_SUPPORT_PKG + "/.LauncherCallbackTestsService";
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+              + getDevice().executeShellCommand(command));
+
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsMultiUserTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsMultiUserTest.java
new file mode 100644
index 0000000..0af38a4
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsMultiUserTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.devicepolicy;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+/**
+ * Set of tests for LauncherApps attempting to access a non-profiles
+ * apps.
+ */
+public class LauncherAppsMultiUserTest extends BaseLauncherAppsTest {
+
+    private int mSecondaryUserId;
+    private int mSecondaryUserSerialNumber;
+
+    private boolean mMultiUserSupported;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // We need multi user to be supported in order to create a secondary user
+        // and api level 21 to support LauncherApps
+        mMultiUserSupported = getMaxNumberOfUsersSupported() > 1 && getDevice().getApiLevel() >= 21;
+
+        if (mMultiUserSupported) {
+            removeTestUsers();
+            installTestApps();
+            // Create a secondary user.
+            mSecondaryUserId = createUser();
+            mSecondaryUserSerialNumber = getUserSerialNumber(mSecondaryUserId);
+            startUser(mSecondaryUserId);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mMultiUserSupported) {
+            removeUser(mSecondaryUserId);
+            uninstallTestApps();
+        }
+        super.tearDown();
+    }
+
+    public void testGetActivitiesForNonProfileFails() throws Exception {
+        if (!mMultiUserSupported) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                    "testGetActivitiesForUserFails",
+                            0, "-e testUser " + mSecondaryUserSerialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testNoLauncherCallbackPackageAddedSecondaryUser() throws Exception {
+        if (!mMultiUserSupported) {
+            return;
+        }
+        startCallbackService();
+        installApp(SIMPLE_APP_APK);
+        try {
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                            "testNoCallbackForUser",
+                            0, "-e testUser " + mSecondaryUserSerialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java
new file mode 100644
index 0000000..f8c2e7d
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsProfileTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.devicepolicy;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+/**
+ * Set of tests for LauncherApps with managed profiles.
+ */
+public class LauncherAppsProfileTest extends BaseLauncherAppsTest {
+
+    private int mProfileUserId;
+    private int mProfileSerialNumber;
+    private int mMainUserSerialNumber;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // We need multi user to be supported in order to create a profile of the user owner.
+        mHasFeature = mHasFeature && (getMaxNumberOfUsersSupported() > 1);
+
+        if (mHasFeature) {
+            removeTestUsers();
+            installTestApps();
+            // Create a managed profile
+            mProfileUserId = createManagedProfile();
+            installApp(MANAGED_PROFILE_APK);
+            setProfileOwner(MANAGED_PROFILE_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS, mProfileUserId);
+            mProfileSerialNumber = getUserSerialNumber(mProfileUserId);
+            mMainUserSerialNumber = getUserSerialNumber(0);
+            startUser(mProfileUserId);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHasFeature) {
+            removeUser(mProfileUserId);
+            uninstallTestApps();
+            getDevice().uninstallPackage(MANAGED_PROFILE_PKG);
+        }
+        super.tearDown();
+    }
+
+    public void testGetActivitiesWithProfile() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        // Install app for all users.
+        installApp(SIMPLE_APP_APK);
+        try {
+            // Run tests to check SimpleApp exists in both profile and main user.
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                    "testSimpleAppInstalledForUser",
+                            0, "-e testUser " + mProfileSerialNumber));
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_PKG + ".LauncherAppsTests", "testSimpleAppInstalledForUser",
+                            0, "-e testUser " + mMainUserSerialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLauncherCallbackPackageAddedProfile() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        startCallbackService();
+        installApp(SIMPLE_APP_APK);
+        try {
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                            "testPackageAddedCallbackForUser",
+                            0, "-e testUser " + mProfileSerialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLauncherCallbackPackageRemovedProfile() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            startCallbackService();
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                            "testPackageRemovedCallbackForUser",
+                            0, "-e testUser " + mProfileSerialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLauncherCallbackPackageChangedProfile() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            startCallbackService();
+            installApp(SIMPLE_APP_APK);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                            "testPackageChangedCallbackForUser",
+                            0, "-e testUser " + mProfileSerialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsSingleUserTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsSingleUserTest.java
new file mode 100644
index 0000000..32be962
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/LauncherAppsSingleUserTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.devicepolicy;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+/**
+ * Set of tests for LauncherApps with managed profiles.
+ */
+public class LauncherAppsSingleUserTest extends BaseLauncherAppsTest {
+
+    private boolean mHasLauncherApps;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mHasLauncherApps = getDevice().getApiLevel() >= 21;
+
+        if (mHasLauncherApps) {
+            installTestApps();
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHasLauncherApps) {
+            uninstallTestApps();
+        }
+        super.tearDown();
+    }
+
+    public void testInstallAppMainUser() throws Exception {
+        if (!mHasLauncherApps) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            int serialNumber = getUserSerialNumber(0);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS, "testSimpleAppInstalledForUser",
+                            0, "-e testUser " + serialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLauncherCallbackPackageAddedMainUser() throws Exception {
+        if (!mHasLauncherApps) {
+            return;
+        }
+        startCallbackService();
+        installApp(SIMPLE_APP_APK);
+        try {
+            int serialNumber = getUserSerialNumber(0);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                            "testPackageAddedCallbackForUser",
+                            0, "-e testUser " + serialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLauncherCallbackPackageRemovedMainUser() throws Exception {
+        if (!mHasLauncherApps) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            startCallbackService();
+            int serialNumber = getUserSerialNumber(0);
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                            "testPackageRemovedCallbackForUser",
+                            0, "-e testUser " + serialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLauncherCallbackPackageChangedMainUser() throws Exception {
+        if (!mHasLauncherApps) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            startCallbackService();
+            int serialNumber = getUserSerialNumber(0);
+            installApp(SIMPLE_APP_APK);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS,
+                            "testPackageChangedCallbackForUser",
+                            0, "-e testUser " + serialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLauncherNonExportedAppFails() throws Exception {
+        if (!mHasLauncherApps) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            int serialNumber = getUserSerialNumber(0);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS, "testLaunchNonExportActivityFails",
+                            0, "-e testUser " + serialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLaunchNonExportActivityFails() throws Exception {
+        if (!mHasLauncherApps) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            int serialNumber = getUserSerialNumber(0);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS, "testLaunchNonExportLauncherFails",
+                            0, "-e testUser " + serialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+
+    public void testLaunchMainActivity() throws Exception {
+        if (!mHasLauncherApps) {
+            return;
+        }
+        installApp(SIMPLE_APP_APK);
+        try {
+            int serialNumber = getUserSerialNumber(0);
+            assertTrue(runDeviceTests(LAUNCHER_TESTS_PKG,
+                    LAUNCHER_TESTS_CLASS, "testLaunchMainActivity",
+                            0, "-e testUser " + serialNumber));
+        } finally {
+            getDevice().uninstallPackage(SIMPLE_APP_PKG);
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 08b2f67..815a453 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -196,27 +196,4 @@
                 "Output for command " + adbCommand + ": " + commandOutput);
         return commandOutput;
     }
-
-    private int createManagedProfile() throws DeviceNotAvailableException {
-        String command =
-                "pm create-user --profileOf 0 --managed TestProfile_" + System.currentTimeMillis();
-        String commandOutput = getDevice().executeShellCommand(command);
-        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
-
-        // Extract the id of the new user.
-        String[] tokens = commandOutput.split("\\s+");
-        assertTrue(commandOutput + " expected to have format \"Success: {USER_ID}\"",
-                tokens.length > 0);
-        assertEquals(commandOutput, "Success:", tokens[0]);
-        return Integer.parseInt(tokens[tokens.length-1]);
-    }
-
-    private void setProfileOwner(String componentName, int userId)
-            throws DeviceNotAvailableException {
-        String command = "dpm set-profile-owner '" + componentName + "' " + userId;
-        String commandOutput = getDevice().executeShellCommand(command);
-        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
-        assertTrue(commandOutput + " expected to start with \"Success:\"",
-                commandOutput.startsWith("Success:"));
-    }
 }
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
index a42ee8a..50e0226 100644
--- a/hostsidetests/security/Android.mk
+++ b/hostsidetests/security/Android.mk
@@ -28,6 +28,7 @@
 LOCAL_CTS_TEST_PACKAGE := android.host.security
 
 LOCAL_JAVA_RESOURCE_FILES := $(HOST_OUT_EXECUTABLES)/sepolicy-analyze
+LOCAL_JAVA_RESOURCE_FILES += $(call intermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
 
 include $(BUILD_CTS_HOST_JAVA_LIBRARY)
 
diff --git a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
new file mode 100644
index 0000000..18d6a17
--- /dev/null
+++ b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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 android.cts.security;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.String;
+import java.net.URL;
+import java.util.Scanner;
+
+/**
+ * Host-side SELinux tests.
+ *
+ * These tests analyze the policy file in use on the subject device directly or
+ * run as the shell user to evaluate aspects of the state of SELinux on the test
+ * device which otherwise would not be available to a normal apk.
+ */
+public class SELinuxHostTest extends DeviceTestCase {
+
+    private File sepolicyAnalyze;
+    private File devicePolicyFile;
+
+    /**
+     * A reference to the device under test.
+     */
+    private ITestDevice mDevice;
+
+    private File copyResourceToTempFile(String resName) throws IOException {
+        InputStream is = this.getClass().getResourceAsStream(resName);
+        File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
+        FileOutputStream os = new FileOutputStream(tempFile);
+        int rByte = 0;
+        while ((rByte = is.read()) != -1) {
+            os.write(rByte);
+        }
+        os.flush();
+        os.close();
+        tempFile.deleteOnExit();
+        return tempFile;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDevice = getDevice();
+
+        /* retrieve the sepolicy-analyze executable from jar */
+        sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
+        sepolicyAnalyze.setExecutable(true);
+
+        /* obtain sepolicy file from running device */
+        devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
+        devicePolicyFile.deleteOnExit();
+        mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy",
+                devicePolicyFile.getAbsolutePath());
+    }
+
+    /**
+     * Tests that all domains in the running policy file are in enforcing mode
+     *
+     * @throws Exception
+     */
+    public void testAllEnforcing() throws Exception {
+
+        /* run sepolicy-analyze permissive check on policy file */
+        ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(), "-p", "-P",
+                devicePolicyFile.getAbsolutePath());
+        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+        pb.redirectErrorStream(true);
+        Process p = pb.start();
+        p.waitFor();
+        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+        String line;
+        StringBuilder errorString = new StringBuilder();
+        while ((line = result.readLine()) != null) {
+            errorString.append(line);
+            errorString.append("\n");
+        }
+        assertTrue("The following SELinux domains were found to be in permissive mode:\n"
+                   + errorString, errorString.length() == 0);
+    }
+
+    /**
+     * Checks the policy running on-device against a set of neverallow rules
+     *
+     * @throws Exception
+     */
+    public void testNeverallowRules() throws Exception {
+
+        File neverallowRules = copyResourceToTempFile("/general_sepolicy.conf");
+
+        /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
+        ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+                "-n", neverallowRules.getAbsolutePath(), "-P",
+                devicePolicyFile.getAbsolutePath());
+        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+        pb.redirectErrorStream(true);
+        Process p = pb.start();
+        p.waitFor();
+        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+        String line;
+        StringBuilder errorString = new StringBuilder();
+        while ((line = result.readLine()) != null) {
+            errorString.append(line);
+            errorString.append("\n");
+        }
+        assertTrue("The following errors were encountered when validating the SELinux"
+                   + "neverallow rules:\n" + errorString, errorString.length() == 0);
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
deleted file mode 100644
index e2c98fe..0000000
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ /dev/null
@@ -1,100 +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 android.security.cts;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.FileOutputStream;
-import java.lang.String;
-import java.net.URL;
-import java.util.Scanner;
-
-/**
- * Host-side SELinux tests.
- *
- * These tests analyze the policy file in use on the subject device directly or
- * run as the shell user to evaluate aspects of the state of SELinux on the test
- * device which otherwise would not be available to a normal apk.
- */
-public class SELinuxHostTest extends DeviceTestCase {
-
-    /**
-     * A reference to the device under test.
-     */
-    private ITestDevice mDevice;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mDevice = getDevice();
-    }
-
-    /**
-     * Tests that all domains in the running policy file are in enforcing mode
-     *
-     * @throws Exception
-     */
-    public void testAllEnforcing() throws Exception {
-
-        /* retrieve the sepolicy-analyze executable from jar */
-        InputStream is = this.getClass().getResourceAsStream("/sepolicy-analyze");
-        File execFile = File.createTempFile("sepolicy-analyze", ".tmp");
-        FileOutputStream os = new FileOutputStream(execFile);
-        int rByte = 0;
-        while ((rByte = is.read()) != -1) {
-            os.write(rByte);
-        }
-        os.flush();
-        os.close();
-        execFile.setExecutable(true);
-
-        /* obtain sepolicy file from running device */
-        File policyFile = File.createTempFile("sepolicy", ".tmp");
-        mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy", policyFile.getAbsolutePath());
-
-        /* run sepolicy-analyze permissive check on policy file */
-        ProcessBuilder pb = new ProcessBuilder(execFile.getAbsolutePath(), "-p", "-P",
-                policyFile.getAbsolutePath());
-        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
-        pb.redirectErrorStream(true);
-        Process p = pb.start();
-        p.waitFor();
-        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
-        String line;
-        StringBuilder errorString = new StringBuilder();
-        while ((line = result.readLine()) != null) {
-            errorString.append(line);
-            errorString.append("\n");
-        }
-
-        /* clean up and check condition */
-        execFile.delete();
-        policyFile.delete();
-        assertTrue("The following SELinux domains were found to be in permissive mode:\n"
-                   + errorString, errorString.length() == 0);
-    }
-}
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index e763a9b..48e5194 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -155,7 +155,24 @@
   bug: 17508787
 },
 {
-
+  description: "New tests recently added for Android Enterprise. To be moved out of CTS-staging as soon as they show that they are stable",
+  names: [
+    "com.android.cts.devicepolicy.LauncherAppsMultiUserTest#testGetActivitiesForNonProfileFails",
+    "com.android.cts.devicepolicy.LauncherAppsMultiUserTest#testNoLauncherCallbackPackageAddedSecondaryUser",
+    "com.android.cts.devicepolicy.LauncherAppsProfileTest#testGetActivitiesWithProfile",
+    "com.android.cts.devicepolicy.LauncherAppsProfileTest#testLauncherCallbackPackageAddedProfile",
+    "com.android.cts.devicepolicy.LauncherAppsProfileTest#testLauncherCallbackPackageRemovedProfile",
+    "com.android.cts.devicepolicy.LauncherAppsProfileTest#testLauncherCallbackPackageChangedProfile",
+    "com.android.cts.devicepolicy.LauncherAppsSingleUserTest#testInstallAppMainUser",
+    "com.android.cts.devicepolicy.LauncherAppsSingleUserTest#testLauncherCallbackPackageAddedMainUser",
+    "com.android.cts.devicepolicy.LauncherAppsSingleUserTest#testLauncherCallbackPackageRemovedMainUser",
+    "com.android.cts.devicepolicy.LauncherAppsSingleUserTest#testLauncherCallbackPackageChangedMainUser",
+    "com.android.cts.devicepolicy.LauncherAppsSingleUserTest#testLauncherNonExportedAppFails",
+    "com.android.cts.devicepolicy.LauncherAppsSingleUserTest#testLaunchNonExportActivityFails",
+    "com.android.cts.devicepolicy.LauncherAppsSingleUserTest#testLaunchMainActivity"
+  ]
+},
+{
   description: "These tests fail on some devices.",
   names: [
     "android.uirendering.cts.testclasses.ExactCanvasTests#testBlueRect",
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index de58783..c41ee58 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -34,22 +34,6 @@
 
 LOCAL_SDK_VERSION := current
 
-intermediates.COMMON := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)
-
-sepolicy_asset_dir := $(intermediates.COMMON)/assets
-
-LOCAL_ASSET_DIR := $(sepolicy_asset_dir)
-
 include $(BUILD_CTS_PACKAGE)
 
-selinux_policy.xml := $(sepolicy_asset_dir)/selinux_policy.xml
-selinux_policy_parser := cts/tools/selinux/src/gen_SELinux_CTS.py
-general_sepolicy_policy.conf := $(call intermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
-$(selinux_policy.xml): PRIVATE_POLICY_PARSER := $(selinux_policy_parser)
-$(selinux_policy.xml): $(general_sepolicy_policy.conf) $(selinux_policy_parser)
-	mkdir -p $(dir $@)
-	$(PRIVATE_POLICY_PARSER) $< $@ neverallow_only=t
-
-$(R_file_stamp): $(selinux_policy.xml)
-
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java b/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java
deleted file mode 100644
index d06fd75..0000000
--- a/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java
+++ /dev/null
@@ -1,162 +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 android.security.cts;
-
-import android.util.Xml;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.HashMap;
-
-
-/**
- * A class for generating representations of SELinux avc rules parsed from an xml file.
- */
-public class SELinuxPolicyRule {
-    public final List<String> source_types;
-    public final List<String> target_types;
-    public final Multimap<String, String> obj_classes;
-    public final String name;
-    public final String type;
-
-    private SELinuxPolicyRule(List<String> source_types, List<String> target_types,
-            Multimap<String, String> obj_classes, String name, String type) {
-        this.source_types = source_types;
-        this.target_types = target_types;
-        this.obj_classes = obj_classes;
-        this.name = name;
-        this.type = type;
-    }
-
-    public static SELinuxPolicyRule readRule(XmlPullParser xpp) throws IOException, XmlPullParserException {
-        List<String> source_types = new ArrayList<String>();
-        List<String> target_types = new ArrayList<String>();
-        Multimap<String, String> obj_classes = HashMultimap.create();
-        xpp.require(XmlPullParser.START_TAG, null, "avc_rule");
-        String ruleName = xpp.getAttributeValue(null, "name");
-        String ruleType = xpp.getAttributeValue(null, "type");
-        while (xpp.next() != XmlPullParser.END_TAG) {
-            if (xpp.getEventType() != XmlPullParser.START_TAG) {
-                continue;
-            }
-            String name = xpp.getName();
-            if (name.equals("type")) {
-                if (xpp.getAttributeValue(null, "type").equals("source")) {
-                    source_types.add(readType(xpp));
-                } else if (xpp.getAttributeValue(null, "type").equals("target")) {
-                    target_types.add(readType(xpp));
-                } else {
-                    skip(xpp);
-                }
-            } else if (name.equals("obj_class")) {
-                String obj_name = xpp.getAttributeValue(null, "name");
-                List<String> perms = readObjClass(xpp);
-                obj_classes.putAll(obj_name, perms);
-            } else {
-                skip(xpp);
-            }
-        }
-        return new SELinuxPolicyRule(source_types, target_types, obj_classes, ruleName, ruleType);
-    }
-
-    public static List<SELinuxPolicyRule> readRulesFile(InputStream in) throws IOException, XmlPullParserException {
-        List<SELinuxPolicyRule> rules = new ArrayList<SELinuxPolicyRule>();
-        XmlPullParser xpp = Xml.newPullParser();
-        xpp.setInput(in, null);
-        xpp.nextTag();
-        xpp.require(XmlPullParser.START_TAG, null, "SELinux_AVC_Rules");
-
-        /* read rules */
-        while (xpp.next()  != XmlPullParser.END_TAG) {
-            if (xpp.getEventType() != XmlPullParser.START_TAG) {
-                continue;
-            }
-            String name = xpp.getName();
-            if (name.equals("avc_rule")) {
-                SELinuxPolicyRule r = readRule(xpp);
-                rules.add(r);
-            } else {
-                skip(xpp);
-            }
-        }
-        return rules;
-    }
-
-    private static List<String> readObjClass(XmlPullParser xpp) throws IOException, XmlPullParserException {
-        List<String> perms = new ArrayList<String>();
-        xpp.require(XmlPullParser.START_TAG, null, "obj_class");
-        while (xpp.next() != XmlPullParser.END_TAG) {
-        if (xpp.getEventType() != XmlPullParser.START_TAG) {
-                continue;
-            }
-            String name = xpp.getName();
-            if (name.equals("permission")) {
-                perms.add(readPermission(xpp));
-            } else {
-                skip(xpp);
-            }
-        }
-        return perms;
-    }
-
-    private static String readType(XmlPullParser xpp) throws IOException, XmlPullParserException {
-        xpp.require(XmlPullParser.START_TAG, null, "type");
-        String type = readText(xpp);
-        xpp.require(XmlPullParser.END_TAG, null, "type");
-        return type;
-    }
-
-    private static String readPermission(XmlPullParser xpp) throws IOException, XmlPullParserException {
-        xpp.require(XmlPullParser.START_TAG, null, "permission");
-        String permission = readText(xpp);
-        xpp.require(XmlPullParser.END_TAG, null, "permission");
-        return permission;
-    }
-
-    private static String readText(XmlPullParser xpp) throws IOException, XmlPullParserException {
-        String result = "";
-        if (xpp.next() == XmlPullParser.TEXT) {
-            result = xpp.getText();
-            xpp.nextTag();
-        }
-        return result;
-    }
-
-    public static void skip(XmlPullParser xpp) throws XmlPullParserException, IOException {
-        if (xpp.getEventType() != XmlPullParser.START_TAG) {
-            throw new IllegalStateException();
-        }
-        int depth = 1;
-        while (depth != 0) {
-            switch (xpp.next()) {
-            case XmlPullParser.END_TAG:
-                depth--;
-                break;
-            case XmlPullParser.START_TAG:
-                depth++;
-                break;
-            }
-        }
-    }
-}
diff --git a/tests/tests/security/src/android/security/cts/SELinuxTest.java b/tests/tests/security/src/android/security/cts/SELinuxTest.java
index 8e57037..711cb91 100644
--- a/tests/tests/security/src/android/security/cts/SELinuxTest.java
+++ b/tests/tests/security/src/android/security/cts/SELinuxTest.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.res.AssetManager;
-import android.security.cts.SELinuxPolicyRule;
 import android.test.AndroidTestCase;
 
 import junit.framework.TestCase;
@@ -82,130 +81,6 @@
         assertEquals(0, files.length);
     }
 
-    /**
-     * Verify all of the rules described by the selinux_policy.xml file are in effect.  Allow rules
-     * should return access granted, and Neverallow should return access denied.  All checks are run
-     * and then a list of specific failed checks is printed.
-     */
-    public void testSELinuxPolicyFile() throws IOException, XmlPullParserException {
-        List<String> failedChecks = new ArrayList<String>();
-        Map<String, Boolean> contextsCache = new HashMap<String, Boolean>();
-        int invalidContextsCount = 0;
-        int totalChecks = 0;
-        int totalFailedChecks = 0;
-        AssetManager assets = mContext.getAssets();
-        InputStream in = assets.open("selinux_policy.xml");
-        Collection<SELinuxPolicyRule> rules = SELinuxPolicyRule.readRulesFile(in);
-        for (SELinuxPolicyRule r : rules) {
-            PolicyFileTestResult result = runRuleChecks(r, contextsCache);
-            totalChecks += result.numTotalChecks;
-            if (result.numFailedChecks != 0) {
-                totalFailedChecks += result.numFailedChecks;
-
-                /* print failures to log, so as not to run OOM in the event of large policy mismatch,
-                   but record actual rule type and number */
-                failedChecks.add("SELinux avc rule " + r.type + r.name + " failed " + result.numFailedChecks +
-                        " out of " + result.numTotalChecks + " checks.");
-                for (String k : result.failedChecks) {
-                    System.out.println(r.type + r.name + " failed " + k);
-                }
-            }
-        }
-        if (totalFailedChecks != 0) {
-
-            /* print out failed rules, just the rule number and type */
-            for (String k : failedChecks) {
-                System.out.println(k);
-            }
-            System.out.println("Failed SELinux Policy Test: " + totalFailedChecks + " failed out of " + totalChecks);
-        }
-        for (String k : contextsCache.keySet()) {
-            if (!contextsCache.get(k)) {
-                invalidContextsCount++;
-                System.out.println("Invalid SELinux context encountered: " + k);
-            }
-        }
-        System.out.println("SELinuxPolicy Test Encountered: " + invalidContextsCount + " missing contexts out of " + contextsCache.size());
-        assertTrue(totalFailedChecks == 0);
-    }
-
-    /**
-     * A class for containing all of the results we care to know from checking each SELinux rule
-     */
-    private class PolicyFileTestResult {
-        private int numTotalChecks;
-        private int numFailedChecks;
-        private List<String> failedChecks = new ArrayList<String>();
-    }
-
-    private PolicyFileTestResult runRuleChecks(SELinuxPolicyRule r, Map<String, Boolean> contextsCache) {
-        PolicyFileTestResult result = new PolicyFileTestResult();
-
-        /* run checks by going through every possible 4-tuple specified by rule.  Start with class
-           and perm to allow early-exit based on context. */
-        for (String c : r.obj_classes.keySet()) {
-            for (String p : r.obj_classes.get(c)) {
-                for (String s : r.source_types) {
-
-                    /* check source context */
-                    String source_context = createAvcContext(s, false, c, p);
-                    if (!contextsCache.containsKey(source_context)) {
-                        contextsCache.put(source_context, checkSELinuxContext(source_context));
-                    }
-                    if (!contextsCache.get(source_context)) {
-                        continue;
-                    }
-                    for (String t : r.target_types) {
-                        if (t.equals("self")) {
-                            t = s;
-                        }
-
-                        /* check target context */
-                        String target_context = createAvcContext(t, true, c, p);
-                        if (!contextsCache.containsKey(target_context)) {
-                            contextsCache.put(target_context, checkSELinuxContext(target_context));
-                        }
-                        if (!contextsCache.get(target_context)) {
-                            continue;
-                        }
-                        boolean canAccess  = checkSELinuxAccess(source_context, target_context,
-                                c, p, "");
-                        result.numTotalChecks++;
-                        if ((r.type.equals("allow") && !canAccess)
-                                || (r.type.equals("neverallow") && canAccess)) {
-                            String failureNotice = s + ", " + t + ", " + c + ", " + p;
-                            result.numFailedChecks++;
-                            result.failedChecks.add(failureNotice);
-                        }
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    /* createAvcContext - currently uses class type and perm to determine user, role and mls values.
-     *
-     * @param target - false if source domain, true if target.
-     */
-    private String createAvcContext(String domain, boolean target,
-            String obj_class, String perm) {
-        String usr = "u";
-        String role;
-
-        /* understand role labeling better */
-        if (obj_class.equals("filesystem") && perm.equals("associate")) {
-            role = "object_r";
-        } else if(obj_class.equals("process") || obj_class.endsWith("socket")) {
-            role = "r";
-        } else if (target) {
-            role = "object_r";
-        } else {
-            role = "r";
-        }
-        return String.format("%s:%s:%s:s0", usr, role, domain);
-    }
-
     private static native boolean checkSELinuxAccess(String scon, String tcon, String tclass, String perm, String extra);
 
     private static native boolean checkSELinuxContext(String con);