Backport CTS for [Prevent shortcut info package name spoofing]

Test: cts-tradefed run cts -m CtsShortcutManagerTestCases -t android.content.pm.cts.shortcutmanager.ShortcutManagerFakingPublisherTest
Bug: 109824443
Bug: 111128116
Change-Id: Id754ac5a5d97122c06a119658bb65185b12c7d0b
Merged-In: I786c999982ae4861bf7c8a1c84507a0563c29b08
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml
index ee92b8c..bf3562b 100755
--- a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml
+++ b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml
@@ -21,6 +21,14 @@
     <application>
         <activity android:name="Launcher" android:enabled="true" android:exported="false">
         </activity>
+
+        <activity-alias android:name="HomeActivity"
+            android:targetActivity="Launcher">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity-alias>
     </application>
 </manifest>
 
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
index c0f76a6..99c7dc1 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
@@ -129,6 +129,8 @@
         assertExpectException(NullPointerException.class, "action must be set",
                 () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
 
+        setCurrentCaller(getTestContext());
+
         assertExpectException(
                 IllegalArgumentException.class, "Short label must be provided", () -> {
                     ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerFakingPublisherTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerFakingPublisherTest.java
new file mode 100644
index 0000000..baa47b0
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerFakingPublisherTest.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2018 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;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.runCommand;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ShortcutInfo;
+import android.platform.test.annotations.SecurityTest;
+import android.support.test.InstrumentationRegistry;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Assume;
+
+/**
+ * CTS for b/109824443.
+ */
+@SmallTest
+@SecurityTest
+public class ShortcutManagerFakingPublisherTest extends ShortcutManagerCtsTestsBase {
+    private static final String ANOTHER_PACKAGE =
+            "android.content.pm.cts.shortcutmanager.packages.package4";
+
+    private static final ComponentName ANOTHER_HOME_ACTIVITY = new ComponentName(
+            ANOTHER_PACKAGE, "android.content.pm.cts.shortcutmanager.packages.HomeActivity");
+
+    private static final String INVALID_ID =
+            "[ShortcutManagerFakingPublisherTest.shortcut_that_should_not_be_created]";
+
+    @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 testSpoofingPublisher() {
+        final Context myContext = getTestContext();
+        final Context anotherContext;
+        try {
+            anotherContext = getTestContext().createPackageContext(ANOTHER_PACKAGE, 0);
+        } catch (NameNotFoundException e) {
+            fail("Unable to create package context for " + ANOTHER_PACKAGE);
+            return;
+        }
+        final ShortcutInfo invalid = new ShortcutInfo.Builder(anotherContext, INVALID_ID)
+                .setShortLabel(INVALID_ID)
+                .setIntent(new Intent(Intent.ACTION_VIEW))
+                .setActivity(ANOTHER_HOME_ACTIVITY)
+                .build();
+
+        // Check set.
+        runWithCaller(mPackageContext1, () -> {
+            getManager().removeAllDynamicShortcuts();
+
+            assertShortcutPackageMismatch("setDynamicShortcuts1", mPackageContext1, () -> {
+                getManager().setDynamicShortcuts(list(
+                        invalid));
+            });
+            assertInvalidShortcutNotCreated();
+            assertShortcutPackageMismatch("setDynamicShortcuts2A", mPackageContext1, () -> {
+                getManager().setDynamicShortcuts(list(
+                        invalid,
+                        makeShortcut("s1", "title1")));
+            });
+            assertInvalidShortcutNotCreated();
+            assertShortcutPackageMismatch("setDynamicShortcuts2B", mPackageContext1, () -> {
+                getManager().setDynamicShortcuts(list(
+                        makeShortcut("s1", "title1"),
+                        invalid));
+            });
+            assertInvalidShortcutNotCreated();
+        });
+
+        // Check add.
+        runWithCaller(mPackageContext1, () -> {
+            getManager().removeAllDynamicShortcuts();
+
+            assertShortcutPackageMismatch("addDynamicShortcuts1", mPackageContext1, () -> {
+                getManager().addDynamicShortcuts(list(
+                        invalid));
+            });
+            assertInvalidShortcutNotCreated();
+            assertShortcutPackageMismatch("addDynamicShortcuts2A", mPackageContext1, () -> {
+                getManager().addDynamicShortcuts(list(
+                        invalid,
+                        makeShortcut("s1", "title1")));
+            });
+            assertInvalidShortcutNotCreated();
+            assertShortcutPackageMismatch("addDynamicShortcuts2B", mPackageContext1, () -> {
+                getManager().addDynamicShortcuts(list(
+                        makeShortcut("s1", "title1"),
+                        invalid));
+            });
+            assertInvalidShortcutNotCreated();
+        });
+
+        // Check update.
+        runWithCaller(mPackageContext1, () -> {
+            getManager().removeAllDynamicShortcuts();
+
+            assertShortcutPackageMismatch("updateShortcuts1", mPackageContext1, () -> {
+                getManager().updateShortcuts(list(
+                        invalid));
+            });
+            assertInvalidShortcutNotCreated();
+            assertShortcutPackageMismatch("updateShortcuts2A", mPackageContext1, () -> {
+                getManager().updateShortcuts(list(
+                        invalid,
+                        makeShortcut("s1", "title1")));
+            });
+            assertInvalidShortcutNotCreated();
+            assertShortcutPackageMismatch("updateShortcuts2B", mPackageContext1, () -> {
+                getManager().updateShortcuts(list(
+                        makeShortcut("s1", "title1"),
+                        invalid));
+            });
+            assertInvalidShortcutNotCreated();
+        });
+
+        // requestPin (API26 and above)
+        runWithCaller(mPackageContext1, () -> {
+            getManager().removeAllDynamicShortcuts();
+
+            assertShortcutPackageMismatch("requestPinShortcut", mPackageContext1, () -> {
+                getManager().requestPinShortcut(invalid, null);
+            });
+            assertInvalidShortcutNotCreated();
+        });
+
+        // createShortcutResultIntent (API26 and above)
+        runWithCaller(mPackageContext1, () -> {
+            getManager().removeAllDynamicShortcuts();
+
+            assertShortcutPackageMismatch("createShortcutResultIntent", mPackageContext1, () -> {
+                getManager().createShortcutResultIntent(invalid);
+            });
+            assertInvalidShortcutNotCreated();
+        });
+    }
+
+    private void assertInvalidShortcutNotCreated() {
+        for (String s : runCommand(InstrumentationRegistry.getInstrumentation(),
+                "dumpsys shortcut")) {
+            assertFalse("dumpsys shortcut contained invalid ID", s.contains(INVALID_ID));
+        }
+    }
+
+    private void assertShortcutPackageMismatch(String method, Context callerContext, Runnable r) {
+        assertExpectException(
+                "Caller=" + callerContext.getPackageName() + ", method=" + method,
+                SecurityException.class, "Shortcut package name mismatch",
+                () -> runWithCaller(callerContext, () -> r.run())
+        );
+    }
+}