Slight relaxing of Context.getUserId() checks.

Two specific managers have their own strategies using indirection to
obtain Context.getUserId(), and we're willing to special case these
to reduce warning noise.

Bug: 115654727, 159626156
Test: atest error_prone_android_framework_test
Change-Id: I290b74f7b6ec17c647f1cbb9ea7995f3fd56b132
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
index 4f1af3e..3a1bc1e 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/ContextUserIdChecker.java
@@ -18,6 +18,7 @@
 
 import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
 import static com.google.errorprone.bugpatterns.android.UidChecker.getFlavor;
+import static com.google.errorprone.matchers.Matchers.anyOf;
 import static com.google.errorprone.matchers.Matchers.enclosingClass;
 import static com.google.errorprone.matchers.Matchers.hasAnnotation;
 import static com.google.errorprone.matchers.Matchers.instanceMethod;
@@ -60,8 +61,13 @@
 
     private static final Matcher<ExpressionTree> BINDER_CALL = methodInvocation(
             instanceMethod().onDescendantOf("android.os.IInterface").withAnyName());
-    private static final Matcher<ExpressionTree> GET_USER_ID_CALL = methodInvocation(
-            instanceMethod().onDescendantOf("android.content.Context").named("getUserId"));
+    private static final Matcher<ExpressionTree> GET_USER_ID_CALL = methodInvocation(anyOf(
+            instanceMethod().onExactClass("android.app.admin.DevicePolicyManager")
+                    .named("myUserId"),
+            instanceMethod().onExactClass("android.content.pm.ShortcutManager")
+                    .named("injectMyUserId"),
+            instanceMethod().onDescendantOf("android.content.Context")
+                    .named("getUserId")));
 
     private static final Matcher<ExpressionTree> USER_ID_FIELD = new Matcher<ExpressionTree>() {
         @Override
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ContextUserIdCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ContextUserIdCheckerTest.java
index c0b8cd7..c877230 100644
--- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ContextUserIdCheckerTest.java
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ContextUserIdCheckerTest.java
@@ -92,4 +92,56 @@
                         "}")
                 .doTest();
     }
+
+    @Test
+    public void testDevicePolicyManager() {
+        compilationHelper
+                .addSourceFile("/android/annotation/SystemService.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/foo/IFooService.java")
+                .addSourceFile("/android/os/IInterface.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/RemoteException.java")
+                .addSourceLines("DevicePolicyManager.java",
+                        "package android.app.admin;",
+                        "import android.annotation.SystemService;",
+                        "import android.content.Context;",
+                        "import android.foo.IFooService;",
+                        "import android.os.UserHandle;",
+                        "import android.os.RemoteException;",
+                        "@SystemService(\"dp\") public class DevicePolicyManager {",
+                        "  IFooService mService;",
+                        "  int myUserId() { return 0; }",
+                        "  void bar() throws RemoteException {",
+                        "    mService.baz(null, myUserId());",
+                        "  }",
+                        "}")
+                .doTest();
+    }
+
+    @Test
+    public void testShortcutManager() {
+        compilationHelper
+                .addSourceFile("/android/annotation/SystemService.java")
+                .addSourceFile("/android/content/Context.java")
+                .addSourceFile("/android/foo/IFooService.java")
+                .addSourceFile("/android/os/IInterface.java")
+                .addSourceFile("/android/os/UserHandle.java")
+                .addSourceFile("/android/os/RemoteException.java")
+                .addSourceLines("ShortcutManager.java",
+                        "package android.content.pm;",
+                        "import android.annotation.SystemService;",
+                        "import android.content.Context;",
+                        "import android.foo.IFooService;",
+                        "import android.os.UserHandle;",
+                        "import android.os.RemoteException;",
+                        "@SystemService(\"shortcut\") public class ShortcutManager {",
+                        "  IFooService mService;",
+                        "  int injectMyUserId() { return 0; }",
+                        "  void bar() throws RemoteException {",
+                        "    mService.baz(null, injectMyUserId());",
+                        "  }",
+                        "}")
+                .doTest();
+    }
 }