Allow associated companion app to start background activity

Bug: 123272462
Test: Able to compile, will have a follow up CTS
Change-Id: Ic8d6f0df95b426a87711f5432dd7d5aec5a17886
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 3865b27..a7404bc 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -72,7 +72,9 @@
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.FgThread;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.wm.ActivityTaskManagerInternal;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -84,6 +86,7 @@
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -519,6 +522,11 @@
             if (size(old) == size(associations)) return;
 
             Set<Association> finalAssociations = associations;
+            Set<String> companionAppPackages = new HashSet<>();
+            for (Association association : finalAssociations) {
+                companionAppPackages.add(association.companionAppPackage);
+            }
+
             file.write((out) -> {
                 XmlSerializer xml = Xml.newSerializer();
                 try {
@@ -542,6 +550,9 @@
                 }
 
             });
+            ActivityTaskManagerInternal atmInternal = LocalServices.getService(
+                    ActivityTaskManagerInternal.class);
+            atmInternal.setCompanionAppPackages(userId, companionAppPackages);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index ea1db40..47745d5 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1015,6 +1015,11 @@
         if (mService.isDeviceOwner(callingPackage)) {
             return false;
         }
+        // don't abort if the callingPackage has companion device
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        if (mService.isAssociatedCompanionApp(callingUserId, callingPackage)) {
+            return false;
+        }
         // don't abort if the callingPackage is temporarily whitelisted
         if (mService.isPackageNameWhitelistedForBgActivityStarts(callingPackage)) {
             Slog.w(TAG, "Background activity start for " + callingPackage
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index fc7646f..b2e5b6a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -510,4 +510,7 @@
      * Called by DevicePolicyManagerService to set the package name of the device owner.
      */
     public abstract void setDeviceOwnerPackageName(String deviceOwnerPkg);
+
+    /** Set all associated companion app that belongs to an userId. */
+    public abstract void setCompanionAppPackages(int userId, Set<String> companionAppPackages);
 }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index faa98fa..9a8824f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -443,6 +443,9 @@
     // VoiceInteractionManagerService
     ComponentName mActiveVoiceInteractionServiceComponent;
 
+    // A map userId and all its companion app packages
+    private final Map<Integer, Set<String>> mCompanionAppPackageMap = new ArrayMap<>();
+
     VrController mVrController;
     KeyguardController mKeyguardController;
     private final ClientLifecycleManager mLifecycleManager;
@@ -5909,6 +5912,14 @@
         }
     }
 
+    boolean isAssociatedCompanionApp(int userId, String packageName) {
+        final Set<String> allPackages = mCompanionAppPackageMap.get(userId);
+        if (allPackages == null) {
+            return false;
+        }
+        return allPackages.contains(packageName);
+    }
+
     final class H extends Handler {
         static final int REPORT_TIME_TRACKER_MSG = 1;
 
@@ -7282,5 +7293,17 @@
                 ActivityTaskManagerService.this.setDeviceOwnerPackageName(deviceOwnerPkg);
             }
         }
+
+        @Override
+        public void setCompanionAppPackages(int userId, Set<String> companionAppPackages) {
+            // Deep copy all content to make sure we do not rely on the source
+            final Set<String> result = new HashSet<>();
+            for (String pkg : companionAppPackages) {
+                result.add(pkg);
+            }
+            synchronized (mGlobalLock) {
+                mCompanionAppPackageMap.put(userId, result);
+            }
+        }
     }
 }