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