Merge "Support null service resources in ServiceWatcher" into main
diff --git a/location/java/android/location/flags/gnss.aconfig b/location/java/android/location/flags/location.aconfig
similarity index 88%
rename from location/java/android/location/flags/gnss.aconfig
rename to location/java/android/location/flags/location.aconfig
index 8c7c871..32ad09c 100644
--- a/location/java/android/location/flags/gnss.aconfig
+++ b/location/java/android/location/flags/location.aconfig
@@ -1,6 +1,13 @@
 package: "android.location.flags"
 
 flag {
+    name: "fix_service_watcher"
+    namespace: "location"
+    description: "Enable null explicit services in ServiceWatcher"
+    bug: "311210517"
+}
+
+flag {
     name: "gnss_api_navic_l1"
     namespace: "location"
     description: "Flag for GNSS API for NavIC L1"
diff --git a/services/core/java/com/android/server/servicewatcher/CurrentUserServiceSupplier.java b/services/core/java/com/android/server/servicewatcher/CurrentUserServiceSupplier.java
index 6677e7e..1526230 100644
--- a/services/core/java/com/android/server/servicewatcher/CurrentUserServiceSupplier.java
+++ b/services/core/java/com/android/server/servicewatcher/CurrentUserServiceSupplier.java
@@ -36,10 +36,12 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
+import android.location.flags.Flags;
 import android.os.Bundle;
 import android.os.Process;
 import android.os.UserHandle;
 import android.util.Log;
+import android.util.TypedValue;
 
 import com.android.internal.util.Preconditions;
 import com.android.server.FgThread;
@@ -70,6 +72,10 @@
     private static final String EXTRA_SERVICE_VERSION = "serviceVersion";
     private static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";
 
+    // a package value that will never match against any package (we can't use null since this will
+    // match against any package).
+    private static final String NO_MATCH_PACKAGE = "";
+
     private static final Comparator<BoundServiceInfo> sBoundServiceInfoComparator = (o1, o2) -> {
         if (o1 == o2) {
             return 0;
@@ -196,7 +202,19 @@
         Resources resources = context.getResources();
         boolean enableOverlay = resources.getBoolean(enableOverlayResId);
         if (!enableOverlay) {
-            return resources.getString(nonOverlayPackageResId);
+            if (Flags.fixServiceWatcher()) {
+                // we don't use getText() or similar because it won't return null values
+                TypedValue out = new TypedValue();
+                resources.getValue(nonOverlayPackageResId, out, true);
+                CharSequence explicitPackage = out.coerceToString();
+                if (explicitPackage == null) {
+                    return NO_MATCH_PACKAGE;
+                } else {
+                    return explicitPackage.toString();
+                }
+            } else {
+                return resources.getString(nonOverlayPackageResId);
+            }
         } else {
             return null;
         }
@@ -233,6 +251,10 @@
 
     @Override
     public boolean hasMatchingService() {
+        if (Flags.fixServiceWatcher() && NO_MATCH_PACKAGE.equals(mIntent.getPackage())) {
+            return false;
+        }
+
         int intentQueryFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
         if (mMatchSystemAppsOnly) {
             intentQueryFlags |= MATCH_SYSTEM_ONLY;
@@ -268,6 +290,10 @@
 
     @Override
     public BoundServiceInfo getServiceInfo() {
+        if (Flags.fixServiceWatcher() && NO_MATCH_PACKAGE.equals(mIntent.getPackage())) {
+            return null;
+        }
+
         BoundServiceInfo bestServiceInfo = null;
 
         // only allow services in the correct direct boot state to match