Error prone checks for mutability flags on PI

Add a mutability flag check for all method calls that create a PendingIntent.

Bug: 160794467
Test: atest error_prone_android_framework_test:com.google.errorprone.bugpatterns.android.PendingIntentMutabilityCheckerTest
Change-Id: I26a51a6dddb2793e9a56e72876f3f9d2aea4e3fb
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityChecker.java
new file mode 100644
index 0000000..2561b41
--- /dev/null
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityChecker.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.errorprone.bugpatterns.android;
+
+import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
+import static com.google.errorprone.matchers.FieldMatchers.staticField;
+import static com.google.errorprone.matchers.Matchers.anyOf;
+import static com.google.errorprone.matchers.Matchers.contains;
+import static com.google.errorprone.matchers.Matchers.methodInvocation;
+import static com.google.errorprone.matchers.Matchers.staticMethod;
+
+
+import com.google.auto.service.AutoService;
+import com.google.errorprone.BugPattern;
+import com.google.errorprone.VisitorState;
+import com.google.errorprone.bugpatterns.BugChecker;
+import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
+import com.google.errorprone.matchers.Description;
+import com.google.errorprone.matchers.Matcher;
+import com.sun.source.tree.ExpressionTree;
+import com.sun.source.tree.MethodInvocationTree;
+
+import java.util.regex.Pattern;
+
+/**
+ * Any method calls to create a PendingIntent require that one of the
+ * mutability flags, FLAG_MUTABLE or FLAG_IMMUTABLE, be explicitly specified.
+ * This checker verifies that one of these mutability flags are used when
+ * creating PendingIntents.
+ */
+@AutoService(BugChecker.class)
+@BugPattern(
+        name = "AndroidFrameworkPendingIntentMutability",
+        summary = "Verifies that FLAG_MUTABLE or FLAG_IMMUTABLE is always set",
+        severity = WARNING)
+public final class PendingIntentMutabilityChecker extends BugChecker
+        implements MethodInvocationTreeMatcher {
+
+    private static final Matcher<ExpressionTree> PENDING_INTENT_METHOD = methodInvocation(
+            staticMethod()
+            .onClass("android.app.PendingIntent")
+            .withNameMatching(Pattern.compile(
+                    "^(getActivity|getActivityAsUser|getActivities|getActivitiesAsUser|"
+                    + "getBroadcast|getBroadcastAsUser|getService|getForegroundService).*")));
+
+    private static final Matcher<ExpressionTree> VALID_FLAGS = anyOf(
+            staticField("android.app.PendingIntent", "FLAG_MUTABLE"),
+            staticField("android.app.PendingIntent", "FLAG_IMMUTABLE"));
+
+    private static final Matcher<ExpressionTree> CONTAINS_VALID_FLAGS = contains(
+            ExpressionTree.class, VALID_FLAGS);
+
+    @Override
+    public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
+        if (PENDING_INTENT_METHOD.matches(tree, state)) {
+            final ExpressionTree arg = tree.getArguments().get(3);
+            if (!(VALID_FLAGS.matches(arg, state) || CONTAINS_VALID_FLAGS.matches(arg, state))) {
+                return buildDescription(arg)
+                        .setMessage("To improve security, PendingIntents must declare one of"
+                                + " FLAG_MUTABLE or FLAG_IMMUTABLE explicitly; see"
+                                + " go/immutable-pendingintents for more details")
+                        .build();
+            }
+        }
+        return Description.NO_MATCH;
+    }
+}
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityCheckerTest.java
new file mode 100644
index 0000000..a8badf6
--- /dev/null
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/PendingIntentMutabilityCheckerTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.errorprone.bugpatterns.android;
+
+import com.google.errorprone.CompilationTestHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class PendingIntentMutabilityCheckerTest {
+    private CompilationTestHelper mCompilationHelper;
+
+    @Before
+    public void setUp() {
+        mCompilationHelper = CompilationTestHelper.newInstance(
+                PendingIntentMutabilityChecker.class, getClass());
+    }
+
+    @Test
+    public void testGetActivity() {
+        mCompilationHelper
+                .addSourceFile("/android/app/PendingIntent.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/Bundle.java")
+                .addSourceLines("Example.java",
+                        "import android.app.PendingIntent;",
+                        "import android.content.Context;",
+                        "import android.content.Intent;",
+                        "public class Example {",
+                        "  Context context;",
+                        "  Intent intent;",
+                        "  void example() {",
+                        "    PendingIntent.getActivity(context, 42, intent, PendingIntent.FLAG_MUTABLE);",
+                        "    PendingIntent.getActivity(context, 42, intent, PendingIntent.FLAG_IMMUTABLE);",
+                        "    PendingIntent.getActivity(context, 42, intent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);",
+                        "    PendingIntent.getActivity(context, 42, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);",
+                        "    PendingIntent.getActivity(context, 42, intent, 0 | PendingIntent.FLAG_MUTABLE);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivity(context, 42, intent, PendingIntent.FLAG_ONE_SHOT);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivity(context, 42, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivity(context, 42, intent, 0);",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
+    @Test
+    public void testGetActivityAsUser() {
+        mCompilationHelper
+                .addSourceFile("/android/app/PendingIntent.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/Bundle.java")
+                .addSourceLines("Example.java",
+                        "import android.app.PendingIntent;",
+                        "import android.content.Context;",
+                        "import android.content.Intent;",
+                        "public class Example {",
+                        "  Context context;",
+                        "  Intent intent;",
+                        "  void example() {",
+                        "    PendingIntent.getActivityAsUser(context, 42, intent, PendingIntent.FLAG_MUTABLE, null, null);",
+                        "    PendingIntent.getActivityAsUser(context, 42, intent, PendingIntent.FLAG_IMMUTABLE, null, null);",
+                        "    PendingIntent.getActivityAsUser(context, 42, intent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT, null, null);",
+                        "    PendingIntent.getActivityAsUser(context, 42, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT, null, null);",
+                        "    PendingIntent.getActivityAsUser(context, 42, intent, 0 | PendingIntent.FLAG_MUTABLE, null, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivityAsUser(context, 42, intent, PendingIntent.FLAG_ONE_SHOT, null, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivityAsUser(context, 42, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE, null, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivityAsUser(context, 42, intent, 0, null, null);",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
+    @Test
+    public void testGetActivities() {
+        mCompilationHelper
+                .addSourceFile("/android/app/PendingIntent.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/Bundle.java")
+                .addSourceLines("Example.java",
+                        "import android.app.PendingIntent;",
+                        "import android.content.Context;",
+                        "import android.content.Intent;",
+                        "public class Example {",
+                        "  Context context;",
+                        "  Intent[] intents;",
+                        "  void example() {",
+                        "    PendingIntent.getActivities(context, 42, intents, PendingIntent.FLAG_MUTABLE, null);",
+                        "    PendingIntent.getActivities(context, 42, intents, PendingIntent.FLAG_IMMUTABLE, null);",
+                        "    PendingIntent.getActivities(context, 42, intents, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT, null);",
+                        "    PendingIntent.getActivities(context, 42, intents, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT, null);",
+                        "    PendingIntent.getActivities(context, 42, intents, 0 | PendingIntent.FLAG_MUTABLE, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivities(context, 42, intents, PendingIntent.FLAG_ONE_SHOT, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivities(context, 42, intents, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivities(context, 42, intents, 0, null);",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
+    @Test
+    public void testGetActivitiesAsUser() {
+        mCompilationHelper
+                .addSourceFile("/android/app/PendingIntent.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/Bundle.java")
+                .addSourceLines("Example.java",
+                        "import android.app.PendingIntent;",
+                        "import android.content.Context;",
+                        "import android.content.Intent;",
+                        "public class Example {",
+                        "  Context context;",
+                        "  Intent[] intents;",
+                        "  void example() {",
+                        "    PendingIntent.getActivitiesAsUser(context, 42, intents, PendingIntent.FLAG_MUTABLE, null, null);",
+                        "    PendingIntent.getActivitiesAsUser(context, 42, intents, PendingIntent.FLAG_IMMUTABLE, null, null);",
+                        "    PendingIntent.getActivitiesAsUser(context, 42, intents, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT, null, null);",
+                        "    PendingIntent.getActivitiesAsUser(context, 42, intents, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT, null, null);",
+                        "    PendingIntent.getActivitiesAsUser(context, 42, intents, 0 | PendingIntent.FLAG_MUTABLE, null, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivitiesAsUser(context, 42, intents, PendingIntent.FLAG_ONE_SHOT, null, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivitiesAsUser(context, 42, intents, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE, null, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getActivitiesAsUser(context, 42, intents, 0, null, null);",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
+
+    @Test
+    public void testGetBroadcast() {
+        mCompilationHelper
+                .addSourceFile("/android/app/PendingIntent.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/Bundle.java")
+                .addSourceLines("Example.java",
+                        "import android.app.PendingIntent;",
+                        "import android.content.Context;",
+                        "import android.content.Intent;",
+                        "public class Example {",
+                        "  Context context;",
+                        "  Intent intent;",
+                        "  void example() {",
+                        "    PendingIntent.getBroadcast(context, 42, intent, PendingIntent.FLAG_MUTABLE);",
+                        "    PendingIntent.getBroadcast(context, 42, intent, PendingIntent.FLAG_IMMUTABLE);",
+                        "    PendingIntent.getBroadcast(context, 42, intent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);",
+                        "    PendingIntent.getBroadcast(context, 42, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);",
+                        "    PendingIntent.getBroadcast(context, 42, intent, 0 | PendingIntent.FLAG_MUTABLE);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getBroadcast(context, 42, intent, PendingIntent.FLAG_ONE_SHOT);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getBroadcast(context, 42, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getBroadcast(context, 42, intent, 0);",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
+    @Test
+    public void testGetBroadcastAsUser() {
+        mCompilationHelper
+                .addSourceFile("/android/app/PendingIntent.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/Bundle.java")
+                .addSourceLines("Example.java",
+                        "import android.app.PendingIntent;",
+                        "import android.content.Context;",
+                        "import android.content.Intent;",
+                        "public class Example {",
+                        "  Context context;",
+                        "  Intent intent;",
+                        "  void example() {",
+                        "    PendingIntent.getBroadcastAsUser(context, 42, intent, PendingIntent.FLAG_MUTABLE, null);",
+                        "    PendingIntent.getBroadcastAsUser(context, 42, intent, PendingIntent.FLAG_IMMUTABLE, null);",
+                        "    PendingIntent.getBroadcastAsUser(context, 42, intent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT, null);",
+                        "    PendingIntent.getBroadcastAsUser(context, 42, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT, null);",
+                        "    PendingIntent.getBroadcastAsUser(context, 42, intent, 0 | PendingIntent.FLAG_MUTABLE, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getBroadcastAsUser(context, 42, intent, PendingIntent.FLAG_ONE_SHOT, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getBroadcastAsUser(context, 42, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE, null);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getBroadcastAsUser(context, 42, intent, 0, null);",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
+    @Test
+    public void testGetService() {
+        mCompilationHelper
+                .addSourceFile("/android/app/PendingIntent.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/Bundle.java")
+                .addSourceLines("Example.java",
+                        "import android.app.PendingIntent;",
+                        "import android.content.Context;",
+                        "import android.content.Intent;",
+                        "public class Example {",
+                        "  Context context;",
+                        "  Intent intent;",
+                        "  void example() {",
+                        "    PendingIntent.getService(context, 42, intent, PendingIntent.FLAG_MUTABLE);",
+                        "    PendingIntent.getService(context, 42, intent, PendingIntent.FLAG_IMMUTABLE);",
+                        "    PendingIntent.getService(context, 42, intent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);",
+                        "    PendingIntent.getService(context, 42, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);",
+                        "    PendingIntent.getService(context, 42, intent, 0 | PendingIntent.FLAG_MUTABLE);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getService(context, 42, intent, PendingIntent.FLAG_ONE_SHOT);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getService(context, 42, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getService(context, 42, intent, 0);",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
+    @Test
+    public void testGetForegroundService() {
+        mCompilationHelper
+                .addSourceFile("/android/app/PendingIntent.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/content/Intent.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/Bundle.java")
+                .addSourceLines("Example.java",
+                        "import android.app.PendingIntent;",
+                        "import android.content.Context;",
+                        "import android.content.Intent;",
+                        "public class Example {",
+                        "  Context context;",
+                        "  Intent intent;",
+                        "  void example() {",
+                        "    PendingIntent.getForegroundService(context, 42, intent, PendingIntent.FLAG_MUTABLE);",
+                        "    PendingIntent.getForegroundService(context, 42, intent, PendingIntent.FLAG_IMMUTABLE);",
+                        "    PendingIntent.getForegroundService(context, 42, intent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);",
+                        "    PendingIntent.getForegroundService(context, 42, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);",
+                        "    PendingIntent.getForegroundService(context, 42, intent, 0 | PendingIntent.FLAG_MUTABLE);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getForegroundService(context, 42, intent, PendingIntent.FLAG_ONE_SHOT);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getForegroundService(context, 42, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_NO_CREATE);",
+                        "    // BUG: Diagnostic contains:",
+                        "    PendingIntent.getForegroundService(context, 42, intent, 0);",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+}
diff --git a/errorprone/tests/res/android/app/PendingIntent.java b/errorprone/tests/res/android/app/PendingIntent.java
new file mode 100644
index 0000000..a0cdedf
--- /dev/null
+++ b/errorprone/tests/res/android/app/PendingIntent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 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.app;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+public class PendingIntent {
+    public static final int FLAG_ONE_SHOT = 1<<30;
+    public static final int FLAG_IMMUTABLE = 1<<26;
+    public static final int FLAG_MUTABLE = 1<<25;
+    public static final int FLAG_NO_CREATE = 1<<29;
+
+    public static PendingIntent getActivity(Context context, int requestCode,
+            Intent intent, int flags) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static PendingIntent getActivityAsUser(Context context, int requestCode,
+            Intent intent, int flags, Bundle options, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static PendingIntent getActivities(Context context, int requestCode,
+            Intent[] intents, int flags, Bundle options) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static PendingIntent getActivitiesAsUser(Context context, int requestCode,
+            Intent[] intents, int flags, Bundle options, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static PendingIntent getBroadcast(Context context, int requestCode,
+            Intent intent, int flags) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
+            Intent intent, int flags, UserHandle userHandle) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static PendingIntent getService(Context context, int requestCode,
+            Intent intent, int flags) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static PendingIntent getForegroundService(Context context, int requestCode,
+            Intent intent, int flags) {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/errorprone/tests/res/android/content/Intent.java b/errorprone/tests/res/android/content/Intent.java
new file mode 100644
index 0000000..9d22d04
--- /dev/null
+++ b/errorprone/tests/res/android/content/Intent.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 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;
+
+public class Intent {
+}
diff --git a/errorprone/tests/res/android/os/Bundle.java b/errorprone/tests/res/android/os/Bundle.java
new file mode 100644
index 0000000..6d2f7b8
--- /dev/null
+++ b/errorprone/tests/res/android/os/Bundle.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 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.os;
+
+public class Bundle {
+}