ShortcutManager: CTS - first cut
Bug 29612099
Change-Id: I54395debd92c8d14e4aefb923a54eceba41d9deb
diff --git a/tests/tests/shortcutmanager/Android.mk b/tests/tests/shortcutmanager/Android.mk
new file mode 100755
index 0000000..1f6bd27
--- /dev/null
+++ b/tests/tests/shortcutmanager/Android.mk
@@ -0,0 +1,45 @@
+# Copyright (C) 2016 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_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ android-support-v4 \
+ mockito-target \
+ ctsdeviceutil \
+ ctstestrunner \
+ ub-uiautomator \
+ ShortcutManagerTestUtils
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsShortcutManagerTestCases
+
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_SDK_VERSION := test_current
+
+include $(BUILD_CTS_PACKAGE)
+#include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/shortcutmanager/AndroidManifest.xml b/tests/tests/shortcutmanager/AndroidManifest.xml
new file mode 100755
index 0000000..5fa4a79
--- /dev/null
+++ b/tests/tests/shortcutmanager/AndroidManifest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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="android.content.pm.cts.shortcutmanager"
+ android:sharedUserId="android.content.pm.cts.shortcutmanager.packages">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+ <activity android:name="android.content.pm.cts.MyActivity" />
+
+ <activity-alias android:name="non_main"
+ android:targetActivity="android.content.pm.cts.MyActivity" >
+ </activity-alias>
+ <activity-alias android:name="disabled_main"
+ android:targetActivity="android.content.pm.cts.MyActivity"
+ android:enabled="false">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+ <activity-alias android:name="main"
+ android:targetActivity="android.content.pm.cts.MyActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.content.pm.cts.shortcutmanager"
+ android:label="CTS tests for ShortcutManager">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/shortcutmanager/AndroidTest.xml b/tests/tests/shortcutmanager/AndroidTest.xml
new file mode 100644
index 0000000..2955155
--- /dev/null
+++ b/tests/tests/shortcutmanager/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<configuration description="Config for ShortcutManager CTS test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsShortcutManagerTestCases.apk" />
+ <option name="test-file-name" value="CtsShortcutManagerPackage1.apk" />
+ <option name="test-file-name" value="CtsShortcutManagerPackage2.apk" />
+ <option name="test-file-name" value="CtsShortcutManagerPackage3.apk" />
+ <option name="test-file-name" value="CtsShortcutManagerPackage4.apk" />
+ <option name="test-file-name" value="CtsShortcutManagerLauncher1.apk" />
+ <option name="test-file-name" value="CtsShortcutManagerLauncher2.apk" />
+ <option name="test-file-name" value="CtsShortcutManagerLauncher3.apk" />
+ <option name="test-file-name" value="CtsShortcutManagerLauncher4.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.content.pm.cts.shortcutmanager" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/shortcutmanager/packages/Android.mk b/tests/tests/shortcutmanager/packages/Android.mk
new file mode 100644
index 0000000..3d02f9c
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/Android.mk
@@ -0,0 +1,17 @@
+# Copyright (C) 2016 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 $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk b/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk
new file mode 100644
index 0000000..acdb149
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk
@@ -0,0 +1,75 @@
+# Copyright (C) 2016 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 := CtsShortcutManagerLauncher1
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher1
+
+include $(BUILD_CTS_PACKAGE)
+
+#-----------------------------------------------------------
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsShortcutManagerLauncher2
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher2
+
+include $(BUILD_CTS_PACKAGE)
+
+#-----------------------------------------------------------
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsShortcutManagerLauncher3
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher3
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml
new file mode 100755
index 0000000..4290c7f
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 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="android.content.pm.cts.shortcutmanager.packages"
+ android:sharedUserId="android.content.pm.cts.shortcutmanager.packages">
+
+ <application>
+ <activity android:name="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ </activity>
+ <activity-alias android:name="Launcher2"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ </activity-alias>
+ <activity-alias android:name="Launcher3"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ </activity-alias>
+ </application>
+</manifest>
+
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk b/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk
new file mode 100644
index 0000000..4aebb74
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2016 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 := CtsShortcutManagerLauncher4
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher4
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/AndroidManifest.xml
new file mode 100755
index 0000000..c43d574
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 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="android.content.pm.cts.shortcutmanager.packages">
+
+ <application>
+ <activity android:name="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
+
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk b/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk
new file mode 100644
index 0000000..458cb4e
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk
@@ -0,0 +1,74 @@
+# Copyright (C) 2016 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 := CtsShortcutManagerPackage1
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.package1
+
+include $(BUILD_CTS_PACKAGE)
+
+#-----------------------------------------------------------
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsShortcutManagerPackage2
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.package2
+
+include $(BUILD_CTS_PACKAGE)
+
+#-----------------------------------------------------------
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsShortcutManagerPackage3
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.package3
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/packagemanifest/AndroidManifest.xml
new file mode 100755
index 0000000..7354333
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/AndroidManifest.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 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="android.content.pm.cts.shortcutmanager.packages"
+ android:sharedUserId="android.content.pm.cts.shortcutmanager.packages">
+
+ <application>
+ <activity android:name="Launcher"
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ </activity>
+
+ <activity-alias android:name="Launcher2"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher3"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher4"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher5"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_no_main_1"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_no_main_2"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_1"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts1"/>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_2"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_3"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_4"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_5"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_error_1"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcut_error_1"/>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_error_2"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcut_error_2"/>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_error_3"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcut_error_3"/>
+ </activity-alias>
+
+ <activity-alias android:name="Launcher_manifest_error_4"
+ android:enabled="false"
+ android:targetActivity="Launcher">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcut_error_4"/>
+ </activity-alias>
+ </application>
+</manifest>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_1024x4096.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_1024x4096.png
new file mode 100644
index 0000000..9b2371d
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_1024x4096.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_16x64.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_16x64.png
new file mode 100644
index 0000000..ed049fa
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_16x64.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_32x32.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_32x32.png
new file mode 100644
index 0000000..a1e25c1
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_32x32.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_4096x1024.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_4096x1024.png
new file mode 100644
index 0000000..8fec244
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_4096x1024.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_4096x4096.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_4096x4096.png
new file mode 100644
index 0000000..a42ff4d
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_4096x4096.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_512x512.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_512x512.png
new file mode 100644
index 0000000..60304b7
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_512x512.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_64x16.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_64x16.png
new file mode 100644
index 0000000..a0983c7
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_64x16.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_64x64.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_64x64.png
new file mode 100644
index 0000000..7cc9373
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/black_64x64.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/icon1.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/icon1.png
new file mode 100644
index 0000000..64eb294
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/icon1.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/icon2.png b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/icon2.png
new file mode 100644
index 0000000..7502484
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/drawable-nodpi/icon2.png
Binary files differ
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/values/strings.xml b/tests/tests/shortcutmanager/packages/packagemanifest/res/values/strings.xml
new file mode 100644
index 0000000..068c991
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/values/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="label1">Shortcut 1</string>
+ <string name="long_label1">Long shortcut label1</string>
+ <string name="disabled_message1">Shortcut 1 is disabled</string>
+
+ <string name="label2">Shortcut 2</string>
+ <string name="long_label2">Long shortcut label2</string>
+ <string name="disabled_message2">Shortcut 2 is disabled</string>
+
+ <string name="label3">Shortcut 3</string>
+ <string name="long_label3">Long shortcut label3</string>
+ <string name="disabled_message3">Shortcut 3 is disabled</string>
+
+ <string name="label4">Shortcut 4</string>
+ <string name="long_label4">Long shortcut label4</string>
+ <string name="disabled_message4">Shortcut 4 is disabled</string>
+
+ <string name="label5">Shortcut 5</string>
+ <string name="long_label5">Long shortcut label5</string>
+ <string name="disabled_message5">Shortcut 5 is disabled</string>
+</resources>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_1.xml b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_1.xml
new file mode 100644
index 0000000..1737370
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_1.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutShortLabel="@string/label1"
+ >
+ <intent
+ android:action="android.intent.action.VIEW"
+ >
+ </intent>
+ </shortcut>
+ <shortcut
+ android:shortcutId="x1"
+ android:shortcutShortLabel="@string/label1"
+ >
+ <intent
+ android:action="android.intent.action.VIEW"
+ >
+ </intent>
+ </shortcut>
+</shortcuts>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_2.xml b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_2.xml
new file mode 100644
index 0000000..4948e8c
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_2.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="manifest-shortcut-3"
+ >
+ <intent
+ android:action="android.intent.action.VIEW"
+ >
+ </intent>
+ </shortcut>
+ <shortcut
+ android:shortcutId="x2"
+ android:shortcutShortLabel="@string/label1"
+ >
+ <intent
+ android:action="android.intent.action.VIEW"
+ >
+ </intent>
+ </shortcut>
+</shortcuts>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_3.xml b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_3.xml
new file mode 100644
index 0000000..bd76bb7
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_3.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="manifest-shortcut-3"
+ android:shortcutShortLabel="@string/label1"
+ />
+ <shortcut
+ android:shortcutId="x3"
+ android:shortcutShortLabel="@string/label1"
+ >
+ <intent
+ android:action="android.intent.action.VIEW"
+ >
+ </intent>
+ </shortcut>
+</shortcuts>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_4.xml b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_4.xml
new file mode 100644
index 0000000..c59df67
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcut_error_4.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <!-- This is valid -->
+ <shortcut
+ android:shortcutId="ms1"
+ android:shortcutShortLabel="@string/label1"
+ >
+ <intent android:action="action1" />
+ </shortcut>
+
+ <!-- Invalid: no intent -->
+ <shortcut
+ android:shortcutId="ms_ignored1"
+ android:shortcutShortLabel="@string/label1"
+ />
+
+ <!-- Valid: more than one intent; first one will be picked. -->
+ <shortcut
+ android:shortcutId="ms2"
+ android:shortcutShortLabel="@string/label1"
+ >
+ <intent android:action="action2_1" />
+ <intent android:action="action2_2" />
+ </shortcut>
+
+ <!-- Valid: disabled shortcut doesn't need an intent -->
+ <shortcut
+ android:shortcutId="ms3"
+ android:enabled="false"
+ android:shortcutShortLabel="@string/label1"
+ />
+
+ <!-- Valid, but disabled shortcut's intent will be ignored. -->
+ <shortcut
+ android:shortcutId="ms4"
+ android:enabled="false"
+ android:shortcutShortLabel="@string/label1"
+ >
+ <intent android:action="action4" />
+ </shortcut>
+
+ <!-- Invalid, no intent action -->
+ <shortcut
+ android:shortcutId="ms_ignored2"
+ android:shortcutShortLabel="@string/label1"
+ >
+ <intent android:data="x"/>
+ </shortcut>
+</shortcuts>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts1.xml b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts1.xml
new file mode 100644
index 0000000..a3e8472
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts1.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="ms1"
+ android:icon="@drawable/icon1"
+ android:shortcutShortLabel="@string/label1"
+ android:shortcutLongLabel="@string/long_label1"
+ android:shortcutDisabledMessage="@string/disabled_message1">
+ <intent
+ android:action="android.intent.action.VIEW"
+ android:data="http://www.google.com/" />
+ <categories android:name="android.shortcut.conversation" />
+ <categories android:name="android.shortcut.media" />
+ </shortcut>
+</shortcuts>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts2.xml b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts2.xml
new file mode 100644
index 0000000..8b406de
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts2.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="ms21"
+ android:icon="@drawable/icon1"
+ android:shortcutShortLabel="@string/label1"
+ android:shortcutLongLabel="@string/long_label1"
+ android:shortcutDisabledMessage="@string/disabled_message1">
+ <intent
+ android:action="android.intent.action.VIEW"
+ android:data="http://www.google.com/" />
+ <categories android:name="android.shortcut.conversation" />
+ <categories android:name="android.shortcut.media" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="ms22"
+ android:shortcutShortLabel="@string/label2">
+ <intent android:action="android.intent.action.DIAL" />
+ </shortcut>
+</shortcuts>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts3.xml b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts3.xml
new file mode 100644
index 0000000..22f66b3
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/res/xml/shortcuts3.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="ms31"
+ android:icon="@drawable/icon1"
+ android:shortcutShortLabel="@string/label1"
+ android:shortcutLongLabel="@string/long_label1"
+ android:shortcutDisabledMessage="@string/disabled_message1">
+ <intent
+ android:action="android.intent.action.VIEW"
+ android:data="http://www.google.com/" />
+ <categories android:name="android.shortcut.conversation" />
+ <categories android:name="android.shortcut.media" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="ms32"
+ android:shortcutShortLabel="@string/label2">
+ <intent android:action="android.intent.action.DIAL" />
+ </shortcut>
+</shortcuts>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
new file mode 100644
index 0000000..793fa66
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2016 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 := CtsShortcutManagerPackage4
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.package4
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml
new file mode 100755
index 0000000..05c9db7
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 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="android.content.pm.cts.shortcutmanager.packages">
+
+ <application>
+ </application>
+</manifest>
+
diff --git a/tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/Launcher.java b/tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/Launcher.java
new file mode 100644
index 0000000..88db59a
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/Launcher.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.content.pm.cts.shortcutmanager.packages;
+
+import android.app.Activity;
+
+public class Launcher extends Activity {
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/MyActivity.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/MyActivity.java
new file mode 100644
index 0000000..4d1a3e7
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/MyActivity.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.content.pm.cts;
+
+import android.app.Activity;
+
+public class MyActivity extends Activity {
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerCtsTestsBase.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerCtsTestsBase.java
new file mode 100644
index 0000000..10725a9
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerCtsTestsBase.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2016 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.content.pm.cts;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.support.annotation.NonNull;
+import android.test.InstrumentationTestCase;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public abstract class ShortcutManagerCtsTestsBase extends InstrumentationTestCase {
+
+ private static final boolean DUMPSYS_IN_TEARDOWN = true; // DO NOT SUBMIT WITH true
+
+ private static class SpoofingContext extends ContextWrapper {
+ private final String mPackageName;
+
+ public SpoofingContext(Context base, String packageName) {
+ super(base);
+ mPackageName = packageName;
+ }
+
+ @Override
+ public String getPackageName() {
+ return mPackageName;
+ }
+ }
+
+ private Context mCurrentCallerPackage;
+ private int mUserId;
+ private UserHandle mUserHandle;
+
+ private String mOriginalLauncher;
+
+ protected Context mPackageContext1;
+ protected Context mPackageContext2;
+ protected Context mPackageContext3;
+ protected Context mPackageContext4;
+
+ protected Context mLauncherContext1;
+ protected Context mLauncherContext2;
+ protected Context mLauncherContext3;
+ protected Context mLauncherContext4;
+
+ protected LauncherApps mLauncherApps1;
+ protected LauncherApps mLauncherApps2;
+ protected LauncherApps mLauncherApps3;
+ protected LauncherApps mLauncherApps4;
+
+ private Map<Context, ShortcutManager> mManagers = new HashMap<>();
+ private Map<Context, LauncherApps> mLauncherAppses = new HashMap<>();
+
+ private ShortcutManager mCurrentManager;
+ private LauncherApps mCurrentLauncherApps;
+
+ private static class ShortcutActivity extends Activity {
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mUserId = getTestContext().getUserId();
+ mUserHandle = android.os.Process.myUserHandle();
+
+ final String config = getOverrideConfig();
+ if (config != null) {
+ overrideConfig(getInstrumentation(), config);
+ }
+ mOriginalLauncher = getDefaultLauncher(getInstrumentation());
+
+ mPackageContext1 = new SpoofingContext(getTestContext(),
+ "android.content.pm.cts.shortcutmanager.packages.package1");
+ mPackageContext2 = new SpoofingContext(getTestContext(),
+ "android.content.pm.cts.shortcutmanager.packages.package2");
+ mPackageContext3 = new SpoofingContext(getTestContext(),
+ "android.content.pm.cts.shortcutmanager.packages.package3");
+ mPackageContext4 = new SpoofingContext(getTestContext(),
+ "android.content.pm.cts.shortcutmanager.packages.package4");
+ mLauncherContext1 = new SpoofingContext(getTestContext(),
+ "android.content.pm.cts.shortcutmanager.packages.launcher1");
+ mLauncherContext2 = new SpoofingContext(getTestContext(),
+ "android.content.pm.cts.shortcutmanager.packages.launcher2");
+ mLauncherContext3 = new SpoofingContext(getTestContext(),
+ "android.content.pm.cts.shortcutmanager.packages.launcher3");
+ mLauncherContext4 = new SpoofingContext(getTestContext(),
+ "android.content.pm.cts.shortcutmanager.packages.launcher4");
+
+ mLauncherApps1 = new LauncherApps(mLauncherContext1);
+ mLauncherApps2 = new LauncherApps(mLauncherContext2);
+ mLauncherApps3 = new LauncherApps(mLauncherContext3);
+ mLauncherApps4 = new LauncherApps(mLauncherContext4);
+
+ clearShortcuts(getInstrumentation(), mUserId, mPackageContext1.getPackageName());
+ clearShortcuts(getInstrumentation(), mUserId, mPackageContext2.getPackageName());
+ clearShortcuts(getInstrumentation(), mUserId, mPackageContext3.getPackageName());
+ clearShortcuts(getInstrumentation(), mUserId, mPackageContext4.getPackageName());
+
+ setCurrentCaller(mPackageContext1);
+
+ // Make sure shortcuts are removed.
+ withCallers(getAllPublishers(), () -> {
+ assertEquals("for " + getCurrentCallingPackage(),
+ 0, getManager().getDynamicShortcuts().size());
+ assertEquals("for " + getCurrentCallingPackage(),
+ 0, getManager().getPinnedShortcuts().size());
+ });
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (DUMPSYS_IN_TEARDOWN) {
+ dumpsysShortcut(getInstrumentation());
+ }
+
+ resetConfig(getInstrumentation());
+
+ if (!TextUtils.isEmpty(mOriginalLauncher)) {
+ setDefaultLauncher(getInstrumentation(), mOriginalLauncher);
+ }
+
+ super.tearDown();
+ }
+
+ protected Context getTestContext() {
+ return getInstrumentation().getContext();
+ }
+
+ protected UserHandle getUserHandle() {
+ return mUserHandle;
+ }
+
+ protected List<Context> getAllPublishers() {
+ // 4 has a different signature, so we can't call for it.
+ return list(mPackageContext1, mPackageContext2, mPackageContext3);
+ }
+
+ protected List<Context> getAllLaunchers() {
+ // 4 has a different signature, so we can't call for it.
+ return list(mLauncherContext1, mLauncherContext2, mLauncherContext3);
+ }
+
+ protected List<Context> getAllCallers() {
+ return list(
+ mPackageContext1, mPackageContext2, mPackageContext3, mPackageContext4,
+ mLauncherContext1, mLauncherContext2, mLauncherContext3, mLauncherContext4);
+ }
+
+ protected void withCallers(List<Context> callers, Runnable r) {
+ for (Context c : callers) {
+ runWithCaller(c, r);
+ }
+ }
+
+ protected String getOverrideConfig() {
+ return null;
+ }
+
+ protected void setCurrentCaller(Context callerContext) {
+ mCurrentCallerPackage = callerContext;
+
+ if (!mManagers.containsKey(mCurrentCallerPackage)) {
+ mManagers.put(mCurrentCallerPackage, new ShortcutManager(mCurrentCallerPackage));
+ }
+ mCurrentManager = mManagers.get(mCurrentCallerPackage);
+
+ if (!mLauncherAppses.containsKey(mCurrentCallerPackage)) {
+ mLauncherAppses.put(mCurrentCallerPackage, new LauncherApps(mCurrentCallerPackage));
+ }
+ mCurrentLauncherApps = mLauncherAppses.get(mCurrentCallerPackage);
+ }
+
+ protected Context getCurrentCallerContext() {
+ return mCurrentCallerPackage;
+ }
+
+ protected String getCurrentCallingPackage() {
+ return getCurrentCallerContext().getPackageName();
+ }
+
+ protected ShortcutManager getManager() {
+ return mCurrentManager;
+ }
+
+ protected LauncherApps getLauncherApps() {
+ return mCurrentLauncherApps;
+ }
+
+ protected void runWithCaller(Context callerContext, Runnable r) {
+ final Context prev = mCurrentCallerPackage;
+
+ setCurrentCaller(callerContext);
+
+ r.run();
+
+ setCurrentCaller(prev);
+ }
+
+ public static Bundle makeBundle(Object... keysAndValues) {
+ assertTrue((keysAndValues.length % 2) == 0);
+
+ if (keysAndValues.length == 0) {
+ return null;
+ }
+ final Bundle ret = new Bundle();
+
+ for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
+ final String key = keysAndValues[i].toString();
+ final Object value = keysAndValues[i + 1];
+
+ if (value == null) {
+ ret.putString(key, null);
+ } else if (value instanceof Integer) {
+ ret.putInt(key, (Integer) value);
+ } else if (value instanceof String) {
+ ret.putString(key, (String) value);
+ } else if (value instanceof Bundle) {
+ ret.putBundle(key, (Bundle) value);
+ } else {
+ fail("Type not supported yet: " + value.getClass().getName());
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Make a shortcut with an ID.
+ */
+ protected ShortcutInfo makeShortcut(String id) {
+ return makeShortcut(id, "Title-" + id);
+ }
+
+ /**
+ * Make a shortcut with an ID and a title.
+ */
+ protected ShortcutInfo makeShortcut(String id, String shortLabel) {
+ return makeShortcut(
+ id, shortLabel, /* activity =*/ null, /* icon =*/ null,
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ }
+
+ /**
+ * Make a shortcut with an ID and icon.
+ */
+ protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
+ return makeShortcut(
+ id, "Title-" + id, /* activity =*/ null, icon,
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ }
+
+ /**
+ * Make multiple shortcuts with IDs.
+ */
+ protected List<ShortcutInfo> makeShortcuts(String... ids) {
+ final ArrayList<ShortcutInfo> ret = new ArrayList();
+ for (String id : ids) {
+ ret.add(makeShortcut(id));
+ }
+ return ret;
+ }
+
+ protected ShortcutInfo.Builder makeShortcutBuilder(String id) {
+ return new ShortcutInfo.Builder(getCurrentCallerContext(), id);
+ }
+
+ /**
+ * Make a shortcut with details.
+ */
+ protected ShortcutInfo makeShortcut(String id, String shortLabel, ComponentName activity,
+ Icon icon, Intent intent, int rank) {
+ final ShortcutInfo.Builder b = makeShortcutBuilder(id)
+ .setShortLabel(shortLabel)
+ .setRank(rank)
+ .setIntent(intent);
+ if (activity != null) {
+ b.setActivity(activity);
+ }
+ if (icon != null) {
+ b.setIcon(icon);
+ }
+ return b.build();
+ }
+
+ /**
+ * Make an intent.
+ */
+ protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
+ final Intent intent = new Intent(action);
+ intent.setComponent(makeComponent(clazz));
+ intent.replaceExtras(makeBundle(bundleKeysAndValues));
+ return intent;
+ }
+
+ /**
+ * Make an component name, with the client context.
+ */
+ @NonNull
+ protected ComponentName makeComponent(Class<?> clazz) {
+ return new ComponentName(getCurrentCallerContext(), clazz);
+ }
+
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerDynamicCountTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerDynamicCountTest.java
new file mode 100644
index 0000000..7ea95d9
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerDynamicCountTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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.content.pm.cts;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicShortcutCountExceeded;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class ShortcutManagerDynamicCountTest extends ShortcutManagerCtsTestsBase {
+
+ @Override
+ protected String getOverrideConfig() {
+ return "max_shortcuts=3";
+ }
+
+ public void testSetDynamicShortcuts() {
+ runWithCaller(mPackageContext1, () -> {
+ getManager().setDynamicShortcuts(list(makeShortcut("s1")));
+ getManager().setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")));
+
+ assertDynamicShortcutCountExceeded(() -> {
+ getManager().setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
+ makeShortcut("s4")));
+ });
+ });
+ }
+
+ // TODO testAddDynamicShortcuts, update, plus multiple activities.
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerNoThrottlingTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerNoThrottlingTest.java
new file mode 100644
index 0000000..9910309
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerNoThrottlingTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 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.content.pm.cts;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for {@link ShortcutManager} and {@link ShortcutInfo}.
+ *
+ * In this test, we tests the main functionalities of those, without throttling. We
+ */
+@SmallTest
+public class ShortcutManagerNoThrottlingTest extends ShortcutManagerCtsTestsBase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Override
+ protected String getOverrideConfig() {
+ return "reset_interval_sec=999999,"
+ + "max_updates_per_interval=999999,"
+ + "max_shortcuts=10"
+ + "max_icon_dimension_dp=96,"
+ + "max_icon_dimension_dp_lowram=96,"
+ + "icon_format=PNG,"
+ + "icon_quality=100";
+ }
+
+ public void testShortcutInfoMissingMandatoryFields() {
+
+ final ComponentName mainActivity = new ComponentName(
+ getTestContext().getPackageName(), "android.content.pm.cts.shortcutmanager.main");
+
+ assertExpectException(
+ RuntimeException.class,
+ "id cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "id cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), ""));
+
+ assertExpectException(
+ RuntimeException.class,
+ "intents cannot contain null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "action must be set",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
+
+ assertExpectException(
+ RuntimeException.class,
+ "activity cannot be null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setActivity(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "shortLabel cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setShortLabel(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "shortLabel cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setShortLabel(""));
+
+ assertExpectException(
+ RuntimeException.class,
+ "longLabel cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setLongLabel(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "longLabel cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setLongLabel(""));
+
+ assertExpectException(
+ RuntimeException.class,
+ "disabledMessage cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "disabledMessage cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
+
+ assertExpectException(NullPointerException.class, "action must be set",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
+
+ assertExpectException(
+ IllegalArgumentException.class, "Short label must be provided", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .build();
+ assertTrue(getManager().setDynamicShortcuts(list(si)));
+ });
+
+ // same for add.
+ assertExpectException(
+ IllegalArgumentException.class, "Short label must be provided", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(mainActivity)
+ .build();
+ assertTrue(getManager().addDynamicShortcuts(list(si)));
+ });
+
+ assertExpectException(NullPointerException.class, "Intent must be provided", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(mainActivity)
+ .setShortLabel("x")
+ .build();
+ assertTrue(getManager().setDynamicShortcuts(list(si)));
+ });
+
+ // same for add.
+ assertExpectException(NullPointerException.class, "Intent must be provided", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(mainActivity)
+ .setShortLabel("x")
+ .build();
+ assertTrue(getManager().addDynamicShortcuts(list(si)));
+ });
+
+ assertExpectException(
+ IllegalStateException.class, "does not belong to package", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(new ComponentName("xxx", "s"))
+ .build();
+ assertTrue(getManager().setDynamicShortcuts(list(si)));
+ });
+
+ // same for add.
+ assertExpectException(
+ IllegalStateException.class, "does not belong to package", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(new ComponentName("xxx", "s"))
+ .build();
+ assertTrue(getManager().addDynamicShortcuts(list(si)));
+ });
+
+ // Not main activity
+ final ComponentName nonMainActivity = new ComponentName(
+ getTestContext().getPackageName(),
+ "android.content.pm.cts.shortcutmanager.non_main");
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(nonMainActivity)
+ .build();
+ assertTrue(getManager().setDynamicShortcuts(list(si)));
+ });
+ // For add
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(nonMainActivity)
+ .build();
+ assertTrue(getManager().addDynamicShortcuts(list(si)));
+ });
+ // For update
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(nonMainActivity)
+ .build();
+ assertTrue(getManager().updateShortcuts(list(si)));
+ });
+
+ // Main activity, but disabled.
+ final ComponentName disabledMain = new ComponentName(
+ getTestContext().getPackageName(),
+ "android.content.pm.cts.shortcutmanager.disabled_main");
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(disabledMain)
+ .build();
+ assertTrue(getManager().setDynamicShortcuts(list(si)));
+ });
+ // For add
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(disabledMain)
+ .build();
+ assertTrue(getManager().addDynamicShortcuts(list(si)));
+ });
+ // For update
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(disabledMain)
+ .build();
+ assertTrue(getManager().updateShortcuts(list(si)));
+ });
+ }
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofDetectionTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofDetectionTest.java
new file mode 100644
index 0000000..57a5f79
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofDetectionTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 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.content.pm.cts;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.os.Handler;
+import android.os.Looper;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests to make sure the service will detect it when a caller is spoofing the package name
+ * to a package name with a different UID.
+ */
+@SmallTest
+public class ShortcutManagerSpoofDetectionTest extends ShortcutManagerCtsTestsBase {
+
+ @Override
+ protected String getOverrideConfig() {
+ return "max_shortcuts=10";
+ }
+
+ public void assertCallingPackageMismatch(String method, Context callerContext, Runnable r) {
+ assertExpectException(
+ "Caller=" + callerContext.getPackageName() + ", method=" + method,
+ SecurityException.class, "Calling package name mismatch",
+ () -> runWithCaller(callerContext, () -> r.run())
+ );
+ }
+
+ public void testPublisherSpoofing() {
+ assertCallingPackageMismatch("setDynamicShortcuts", mPackageContext4, () -> {
+ getManager().setDynamicShortcuts(list(makeShortcut("s1")));
+ });
+ assertCallingPackageMismatch("addDynamicShortcut", mPackageContext4, () -> {
+ getManager().addDynamicShortcuts(list(makeShortcut("s1")));
+ });
+ assertCallingPackageMismatch("deleteDynamicShortcut", mPackageContext4, () -> {
+ getManager().removeDynamicShortcuts(list("s1"));
+ });
+ assertCallingPackageMismatch("deleteAllDynamicShortcuts", mPackageContext4, () -> {
+ getManager().removeAllDynamicShortcuts();
+ });
+ assertCallingPackageMismatch("getDynamicShortcuts", mPackageContext4, () -> {
+ getManager().getDynamicShortcuts();
+ });
+ assertCallingPackageMismatch("getPinnedShortcuts", mPackageContext4, () -> {
+ getManager().getPinnedShortcuts();
+ });
+ assertCallingPackageMismatch("updateShortcuts", mPackageContext4, () -> {
+ getManager().updateShortcuts(list(makeShortcut("s1")));
+ });
+ assertCallingPackageMismatch("getMaxShortcutCountPerActivity", mPackageContext4, () -> {
+ getManager().getMaxShortcutCountPerActivity();
+ });
+ assertCallingPackageMismatch("getIconMaxWidth", mPackageContext4, () -> {
+ getManager().getIconMaxWidth();
+ });
+ assertCallingPackageMismatch("getIconMaxHeight", mPackageContext4, () -> {
+ getManager().getIconMaxHeight();
+ });
+ }
+
+ public void testLauncherSpoofing() {
+ assertCallingPackageMismatch("hasShortcutHostPermission", mLauncherContext4, () -> {
+ getLauncherApps().hasShortcutHostPermission();
+ });
+
+ assertCallingPackageMismatch("registerCallback", mLauncherContext4, () -> {
+ final LauncherApps.Callback c = mock(LauncherApps.Callback.class);
+ getLauncherApps().registerCallback(c, new Handler(Looper.getMainLooper()));
+ });
+
+ assertCallingPackageMismatch("getShortcuts", mLauncherContext4, () -> {
+ ShortcutQuery q = new ShortcutQuery();
+ getLauncherApps().getShortcuts(q, getUserHandle());
+ });
+
+ assertCallingPackageMismatch("pinShortcuts", mLauncherContext4, () -> {
+ getLauncherApps().pinShortcuts(
+ mPackageContext1.getPackageName(), list(), getUserHandle());
+ });
+
+ assertCallingPackageMismatch("startShortcut 1", mLauncherContext4, () -> {
+ getLauncherApps().startShortcut(makeShortcut("s"), null, null);
+ });
+ assertCallingPackageMismatch("startShortcut 2", mLauncherContext4, () -> {
+ getLauncherApps().startShortcut(mPackageContext1.getPackageName(), "s1",
+ null, null, getUserHandle());
+ });
+ }
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofingTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofingTest.java
new file mode 100644
index 0000000..a401165
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofingTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 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.content.pm.cts;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackNotReceived;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackReceived;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.checkAssertSuccess;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.dumpsysShortcut;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resetAll;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.setDefaultLauncher;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.waitUntil;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
+import android.os.Handler;
+import android.os.Looper;
+
+/**
+ * Make sure switching between mPackageContext1..3 and mLauncherContext1..3 will work as intended.
+ */
+public class ShortcutManagerSpoofingTest extends ShortcutManagerCtsTestsBase {
+ /**
+ * Create shortcuts from different packages and make sure they're really different.
+ */
+ public void testSpoofingPublisher() {
+ runWithCaller(mPackageContext1, () -> {
+ ShortcutInfo s1 = makeShortcut("s1", "title1");
+ getManager().setDynamicShortcuts(list(s1));
+ });
+ runWithCaller(mPackageContext2, () -> {
+ ShortcutInfo s1 = makeShortcut("s1", "title2");
+ getManager().setDynamicShortcuts(list(s1));
+ });
+ runWithCaller(mPackageContext3, () -> {
+ ShortcutInfo s1 = makeShortcut("s1", "title3");
+ getManager().setDynamicShortcuts(list(s1));
+ });
+
+ runWithCaller(mPackageContext1, () -> {
+ assertWith(getManager().getDynamicShortcuts())
+ .haveIds("s1")
+ .forShortcutWithId("s1", s -> {
+ assertEquals("title1", s.getShortLabel());
+ });
+ });
+ runWithCaller(mPackageContext2, () -> {
+ assertWith(getManager().getDynamicShortcuts())
+ .haveIds("s1")
+ .forShortcutWithId("s1", s -> {
+ assertEquals("title2", s.getShortLabel());
+ });
+ });
+ runWithCaller(mPackageContext3, () -> {
+ assertWith(getManager().getDynamicShortcuts())
+ .haveIds("s1")
+ .forShortcutWithId("s1", s -> {
+ assertEquals("title3", s.getShortLabel());
+ });
+ });
+ }
+
+ public void testSpoofingLauncher() {
+ final LauncherApps.Callback c0_1 = mock(LauncherApps.Callback.class);
+ final LauncherApps.Callback c0_2 = mock(LauncherApps.Callback.class);
+ final LauncherApps.Callback c0_3 = mock(LauncherApps.Callback.class);
+ final Handler h = new Handler(Looper.getMainLooper());
+
+ runWithCaller(mLauncherContext1, () -> getLauncherApps().registerCallback(c0_1, h));
+ runWithCaller(mLauncherContext2, () -> getLauncherApps().registerCallback(c0_2, h));
+ runWithCaller(mLauncherContext3, () -> getLauncherApps().registerCallback(c0_3, h));
+
+ // Change the default launcher
+ setDefaultLauncher(getInstrumentation(), mLauncherContext2);
+
+ dumpsysShortcut(getInstrumentation());
+
+ runWithCaller(mLauncherContext1,
+ () -> assertFalse(getLauncherApps().hasShortcutHostPermission()));
+ runWithCaller(mLauncherContext2,
+ () -> assertTrue(getLauncherApps().hasShortcutHostPermission()));
+ runWithCaller(mLauncherContext3,
+ () -> assertFalse(getLauncherApps().hasShortcutHostPermission()));
+
+ // Call a publisher API and make sure only launcher2 gets it.
+
+ resetAll(list(c0_1, c0_2, c0_3));
+
+ runWithCaller(mPackageContext1, () -> {
+ ShortcutInfo s1 = makeShortcut("s1", "title1");
+ getManager().setDynamicShortcuts(list(s1));
+ });
+
+ // Because of the handlers, callback calls are not synchronous.
+ waitUntil("Launcher 2 didn't receive message", () ->
+ checkAssertSuccess(() ->
+ assertCallbackReceived(c0_2, android.os.Process.myUserHandle(),
+ mPackageContext1.getPackageName(), "s1")
+ )
+ );
+
+ assertCallbackNotReceived(c0_1);
+ assertCallbackNotReceived(c0_3);
+ }
+}