Register FederatedComputeManager in SystemServiceRegistry and add
null check during initialization

Test: atest OdpFederatedComputeJobServiceTest; no longer seeing NPE in perf test go/fcp-cuj-perf-testing-instructions
Bug: 298091510
Change-Id: Iebebce3cbcd448480f245785d5b2692fd69b84df
diff --git a/framework/java/android/federatedcompute/FederatedComputeManager.java b/framework/java/android/federatedcompute/FederatedComputeManager.java
index 8342202..1357556 100644
--- a/framework/java/android/federatedcompute/FederatedComputeManager.java
+++ b/framework/java/android/federatedcompute/FederatedComputeManager.java
@@ -49,6 +49,14 @@
  * @hide
  */
 public final class FederatedComputeManager {
+    /**
+     * Constant that represents the service name for {@link FederatedComputeManager} to be used in
+     * {@link android.ondevicepersonalization.OnDevicePersonalizationFrameworkInitializer
+     *      #registerServiceWrappers}
+     *
+     * @hide
+     */
+    public static final String FEDERATED_COMPUTE_SERVICE = "federated_compute_service";
     private static final String TAG = "FederatedComputeManager";
     private static final String FEDERATED_COMPUTATION_SERVICE_INTENT_FILTER_NAME =
             "android.federatedcompute.FederatedComputeService";
@@ -68,7 +76,7 @@
 
     private final Context mContext;
 
-    FederatedComputeManager(Context context) {
+    public FederatedComputeManager(Context context) {
         this.mContext = context;
     }
 
diff --git a/framework/java/android/ondevicepersonalization/OnDevicePersonalizationFrameworkInitializer.java b/framework/java/android/ondevicepersonalization/OnDevicePersonalizationFrameworkInitializer.java
index 36acbe9..bd591e7 100644
--- a/framework/java/android/ondevicepersonalization/OnDevicePersonalizationFrameworkInitializer.java
+++ b/framework/java/android/ondevicepersonalization/OnDevicePersonalizationFrameworkInitializer.java
@@ -18,6 +18,7 @@
 
 import static android.adservices.ondevicepersonalization.OnDevicePersonalizationConfigManager.ON_DEVICE_PERSONALIZATION_CONFIG_SERVICE;
 import static android.adservices.ondevicepersonalization.OnDevicePersonalizationManager.ON_DEVICE_PERSONALIZATION_SERVICE;
+import static android.federatedcompute.FederatedComputeManager.FEDERATED_COMPUTE_SERVICE;
 import static android.ondevicepersonalization.OnDevicePersonalizationSystemServiceManager.ON_DEVICE_PERSONALIZATION_SYSTEM_SERVICE;
 
 import android.adservices.ondevicepersonalization.OnDevicePersonalizationConfigManager;
@@ -25,6 +26,7 @@
 import android.annotation.SystemApi;
 import android.app.SystemServiceRegistry;
 import android.content.Context;
+import android.federatedcompute.FederatedComputeManager;
 
 import com.android.modules.utils.build.SdkLevel;
 
@@ -54,6 +56,9 @@
                 ON_DEVICE_PERSONALIZATION_CONFIG_SERVICE,
                 OnDevicePersonalizationConfigManager.class,
                 (c) -> new OnDevicePersonalizationConfigManager(c));
+        SystemServiceRegistry.registerContextAwareService(
+                FEDERATED_COMPUTE_SERVICE, FederatedComputeManager.class,
+                (c) -> new FederatedComputeManager(c));
 
         if (SdkLevel.isAtLeastU()) {
             SystemServiceRegistry.registerStaticService(
diff --git a/src/com/android/ondevicepersonalization/services/federatedcompute/OdpFederatedComputeJobService.java b/src/com/android/ondevicepersonalization/services/federatedcompute/OdpFederatedComputeJobService.java
index 4d8e23c..29419ac 100644
--- a/src/com/android/ondevicepersonalization/services/federatedcompute/OdpFederatedComputeJobService.java
+++ b/src/com/android/ondevicepersonalization/services/federatedcompute/OdpFederatedComputeJobService.java
@@ -128,6 +128,10 @@
         if (federatedComputeNeedsScheduling()) {
             FederatedComputeManager FCManager =
                     this.getSystemService(FederatedComputeManager.class);
+            if (FCManager == null) {
+                sLogger.e(TAG + ": Failed to get FederatedCompute Service");
+                return;
+            }
             TrainingOptions trainingOptions =
                     new TrainingOptions.Builder().setPopulationName(ODP_POPULATION_NAME).build();
             ScheduleFederatedComputeRequest request =
diff --git a/tests/servicetests/src/com/android/ondevicepersonalization/services/federatedcompute/OdpFederatedComputeJobServiceTest.java b/tests/servicetests/src/com/android/ondevicepersonalization/services/federatedcompute/OdpFederatedComputeJobServiceTest.java
index b0d5a7c..ba90b36 100644
--- a/tests/servicetests/src/com/android/ondevicepersonalization/services/federatedcompute/OdpFederatedComputeJobServiceTest.java
+++ b/tests/servicetests/src/com/android/ondevicepersonalization/services/federatedcompute/OdpFederatedComputeJobServiceTest.java
@@ -17,6 +17,7 @@
 package com.android.ondevicepersonalization.services.federatedcompute;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
@@ -85,6 +86,27 @@
     }
 
     @Test
+    public void onStartJobNullFederatedComputeManagerTest() {
+        MockitoSession session = ExtendedMockito.mockitoSession().spyStatic(
+                OnDevicePersonalizationExecutors.class).strictness(
+                Strictness.LENIENT).startMocking();
+        try {
+            doReturn(null).when(mSpyService).getSystemService(FederatedComputeManager.class);
+            ExtendedMockito.doReturn(MoreExecutors.newDirectExecutorService()).when(
+                    OnDevicePersonalizationExecutors::getBackgroundExecutor);
+            ExtendedMockito.doReturn(MoreExecutors.newDirectExecutorService()).when(
+                    OnDevicePersonalizationExecutors::getLightweightExecutor);
+
+            boolean result = mSpyService.onStartJob(mock(JobParameters.class));
+            assertTrue(result);
+        } catch (Exception e) {
+            fail("An unexpected exception was thrown: " + e.getMessage());
+        } finally {
+            session.finishMocking();
+        }
+    }
+
+    @Test
     public void onStartJobTestKillSwitchEnabled() {
         PhFlagsTestUtil.enableGlobalKillSwitch();
         MockitoSession session =