Add a flag to control whether service error is returned to callers.

Bug: 324478256
Test: TH
Change-Id: I06e8712d45ca93408a456fe50890300744a1c7d1
diff --git a/src/com/android/ondevicepersonalization/services/Flags.java b/src/com/android/ondevicepersonalization/services/Flags.java
index cd83fbc..8e3a263 100644
--- a/src/com/android/ondevicepersonalization/services/Flags.java
+++ b/src/com/android/ondevicepersonalization/services/Flags.java
@@ -96,6 +96,11 @@
      */
     int DEFAULT_BACKGROUND_JOB_SAMPLING_LOGGING_RATE = 5;
 
+    /**
+     * Default value for isolated service debugging flag.
+     */
+    boolean DEFAULT_ISOLATED_SERVICE_DEBUGGING_ENABLED = false;
+
     String DEFAULT_CALLER_APP_ALLOW_LIST =
             "android.ondevicepersonalization,"
                     + "android.ondevicepersonalization.test.scenario,"
@@ -228,6 +233,10 @@
         return DEFAULT_OUTPUT_DATA_ALLOW_LIST;
     }
 
+    default boolean isIsolatedServiceDebuggingEnabled() {
+        return DEFAULT_ISOLATED_SERVICE_DEBUGGING_ENABLED;
+    }
+
     /** Set all stable flags. */
     default void setStableFlags() {}
 
diff --git a/src/com/android/ondevicepersonalization/services/PhFlags.java b/src/com/android/ondevicepersonalization/services/PhFlags.java
index 8d07e1e..b8f3e4a 100644
--- a/src/com/android/ondevicepersonalization/services/PhFlags.java
+++ b/src/com/android/ondevicepersonalization/services/PhFlags.java
@@ -79,6 +79,9 @@
     public static final String KEY_IS_ART_IMAGE_LOADING_OPTIMIZATION_ENABLED =
             "is_art_image_loading_optimization_enabled";
 
+    public static final String KEY_ISOLATED_SERVICE_DEBUGGING_ENABLED =
+            "isolated_service_debugging_enabled";
+
     // OnDevicePersonalization Namespace String from DeviceConfig class
     public static final String NAMESPACE_ON_DEVICE_PERSONALIZATION = "on_device_personalization";
 
@@ -243,6 +246,14 @@
     }
 
     @Override
+    public boolean isIsolatedServiceDebuggingEnabled() {
+        return DeviceConfig.getBoolean(
+                /* namespace= */ NAMESPACE_ON_DEVICE_PERSONALIZATION,
+                /* name= */ KEY_ISOLATED_SERVICE_DEBUGGING_ENABLED,
+                /* defaultValue= */ DEFAULT_ISOLATED_SERVICE_DEBUGGING_ENABLED);
+    }
+
+    @Override
     public String getCallerAppAllowList() {
         return DeviceConfig.getString(
                 /* namespace= */ NAMESPACE_ON_DEVICE_PERSONALIZATION,
diff --git a/src/com/android/ondevicepersonalization/services/util/DebugUtils.java b/src/com/android/ondevicepersonalization/services/util/DebugUtils.java
index 8b35120..331e0b4 100644
--- a/src/com/android/ondevicepersonalization/services/util/DebugUtils.java
+++ b/src/com/android/ondevicepersonalization/services/util/DebugUtils.java
@@ -25,6 +25,7 @@
 import android.provider.Settings;
 
 import com.android.ondevicepersonalization.internal.util.LoggerFactory;
+import com.android.ondevicepersonalization.services.FlagsFactory;
 import com.android.ondevicepersonalization.services.OdpServiceException;
 
 import java.util.Objects;
@@ -48,6 +49,9 @@
             @NonNull ComponentName service,
             @NonNull OdpServiceException e) {
         try {
+            if (!FlagsFactory.getFlags().isIsolatedServiceDebuggingEnabled()) {
+                return 0;
+            }
             if (isDeveloperModeEnabled(context)
                     && PackageUtils.isPackageDebuggable(context, service.getPackageName())) {
                 if (e.getCause() != null && e.getCause() instanceof IsolatedServiceException) {
diff --git a/tests/servicetests/src/com/android/ondevicepersonalization/services/PhFlagsTest.java b/tests/servicetests/src/com/android/ondevicepersonalization/services/PhFlagsTest.java
index 57a7e8a..a2ba05e 100644
--- a/tests/servicetests/src/com/android/ondevicepersonalization/services/PhFlagsTest.java
+++ b/tests/servicetests/src/com/android/ondevicepersonalization/services/PhFlagsTest.java
@@ -39,6 +39,7 @@
 import static com.android.ondevicepersonalization.services.PhFlags.KEY_EXAMPLE_STORE_FLOW_DEADLINE_SECONDS;
 import static com.android.ondevicepersonalization.services.PhFlags.KEY_GLOBAL_KILL_SWITCH;
 import static com.android.ondevicepersonalization.services.PhFlags.KEY_ISOLATED_SERVICE_ALLOW_LIST;
+import static com.android.ondevicepersonalization.services.PhFlags.KEY_ISOLATED_SERVICE_DEBUGGING_ENABLED;
 import static com.android.ondevicepersonalization.services.PhFlags.KEY_IS_ART_IMAGE_LOADING_OPTIMIZATION_ENABLED;
 import static com.android.ondevicepersonalization.services.PhFlags.KEY_ODP_BACKGROUND_JOBS_LOGGING_ENABLED;
 import static com.android.ondevicepersonalization.services.PhFlags.KEY_ODP_BACKGROUND_JOB_SAMPLING_LOGGING_RATE;
@@ -390,6 +391,27 @@
     }
 
     @Test
+    public void testIsolatedServiceDebuggingEnabled() {
+        DeviceConfig.setProperty(
+                DeviceConfig.NAMESPACE_ON_DEVICE_PERSONALIZATION,
+                KEY_ISOLATED_SERVICE_DEBUGGING_ENABLED,
+                Boolean.toString(false),
+                /* makeDefault */ false);
+
+        assertThat(FlagsFactory.getFlags().isIsolatedServiceDebuggingEnabled())
+                .isEqualTo(false);
+
+        DeviceConfig.setProperty(
+                DeviceConfig.NAMESPACE_ON_DEVICE_PERSONALIZATION,
+                KEY_ISOLATED_SERVICE_DEBUGGING_ENABLED,
+                Boolean.toString(true),
+                /* makeDefault */ false);
+
+        assertThat(FlagsFactory.getFlags().isIsolatedServiceDebuggingEnabled())
+                .isEqualTo(true);
+    }
+
+    @Test
     public void testIsArtImageLoadingOptimizationEnabled() {
         assertThat(FlagsFactory.getFlags().isArtImageLoadingOptimizationEnabled())
                 .isEqualTo(IS_ART_IMAGE_LOADING_OPTIMIZATION_ENABLED);
diff --git a/tests/servicetests/src/com/android/ondevicepersonalization/services/util/DebugUtilsTest.java b/tests/servicetests/src/com/android/ondevicepersonalization/services/util/DebugUtilsTest.java
index 61a9272..d793fe2 100644
--- a/tests/servicetests/src/com/android/ondevicepersonalization/services/util/DebugUtilsTest.java
+++ b/tests/servicetests/src/com/android/ondevicepersonalization/services/util/DebugUtilsTest.java
@@ -19,10 +19,15 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.quality.Strictness.LENIENT;
 
+import android.adservices.ondevicepersonalization.Constants;
+import android.adservices.ondevicepersonalization.IsolatedServiceException;
+import android.content.ComponentName;
 import android.content.Context;
 import android.os.Build;
 import android.provider.Settings;
@@ -30,6 +35,9 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.ondevicepersonalization.services.Flags;
+import com.android.ondevicepersonalization.services.FlagsFactory;
+import com.android.ondevicepersonalization.services.OdpServiceException;
 
 import org.junit.After;
 import org.junit.Before;
@@ -45,6 +53,8 @@
         mSession = ExtendedMockito.mockitoSession()
                 .mockStatic(Build.class)
                 .mockStatic(Settings.Global.class)
+                .mockStatic(FlagsFactory.class)
+                .mockStatic(PackageUtils.class)
                 .strictness(LENIENT)
                 .startMocking();
     }
@@ -82,6 +92,63 @@
         assertTrue(DebugUtils.isDeveloperModeEnabled(mContext));
     }
 
+    @Test
+    public void testReturnsExceptionCodeIfDebuggableAndFlagEnabled() {
+        doReturn(new TestFlags(true)).when(FlagsFactory::getFlags);
+        doReturn(true).when(() -> PackageUtils.isPackageDebuggable(any(), any()));
+        enableDeveloperOptions();
+        assertEquals(42,
+                DebugUtils.getIsolatedServiceExceptionCode(
+                        mContext,
+                        new ComponentName("a", "b"),
+                        new OdpServiceException(
+                                Constants.STATUS_SERVICE_FAILED,
+                                new IsolatedServiceException(42))));
+    }
+
+    @Test
+    public void testDoesNotReturnExceptionCodeIfFlagDisabled() {
+        doReturn(new TestFlags(false)).when(FlagsFactory::getFlags);
+        doReturn(true).when(() -> PackageUtils.isPackageDebuggable(any(), any()));
+        enableDeveloperOptions();
+        assertEquals(0,
+                DebugUtils.getIsolatedServiceExceptionCode(
+                        mContext,
+                        new ComponentName("a", "b"),
+                        new OdpServiceException(
+                                Constants.STATUS_SERVICE_FAILED,
+                                new IsolatedServiceException(42))));
+    }
+
+    @Test
+    public void testDoesNotReturnExceptionCodeIfPackageNotDebuggable() {
+        doReturn(new TestFlags(true)).when(FlagsFactory::getFlags);
+        doReturn(false).when(() -> PackageUtils.isPackageDebuggable(any(), any()));
+        enableDeveloperOptions();
+        assertEquals(0,
+                DebugUtils.getIsolatedServiceExceptionCode(
+                        mContext,
+                        new ComponentName("a", "b"),
+                        new OdpServiceException(
+                                Constants.STATUS_SERVICE_FAILED,
+                                new IsolatedServiceException(42))));
+    }
+
+    @Test
+    public void testDoesNotReturnExceptionCodeIfDeviceNotDebuggable() {
+        doReturn(new TestFlags(true)).when(FlagsFactory::getFlags);
+        doReturn(true).when(() -> PackageUtils.isPackageDebuggable(any(), any()));
+        doReturn(false).when(Build::isDebuggable);
+        disableDeveloperOptions();
+        assertEquals(0,
+                DebugUtils.getIsolatedServiceExceptionCode(
+                        mContext,
+                        new ComponentName("a", "b"),
+                        new OdpServiceException(
+                                Constants.STATUS_SERVICE_FAILED,
+                                new IsolatedServiceException(42))));
+    }
+
     private void enableDeveloperOptions() {
         when(Settings.Global.getInt(
                 mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0))
@@ -93,4 +160,14 @@
                 mContext.getContentResolver(), Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0))
                 .thenReturn(0);
     }
+
+    class TestFlags implements Flags {
+        public boolean mIsolatedServiceDebuggingEnabled;
+        TestFlags(boolean value) {
+            mIsolatedServiceDebuggingEnabled = value;
+        }
+        @Override public boolean isIsolatedServiceDebuggingEnabled() {
+            return mIsolatedServiceDebuggingEnabled;
+        }
+    }
 }