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);