Prepare ActivityInterceptorCallback to be unhidden to mainline modules.

AdServices mainline module need to register ActivityInterceptorCallback
as part of Activity Support in SDK Sandbox.

ActivityInterceptorCallback should be visible to mainline modules which
requires the package com.android.server.wm to tagged with Hide annotation,
that is why in this CL a file packge-info.java is added to the package.

This also add fixed to make the class follow go/android-api-guidelines

Test: atest com.android.server.wm.ActivityStartInterceptorTest && atest com.android.server.wm.ActivityTaskManagerServiceTests
Bug: 248531721
CTS-Coverage-Bug: 261596770
API-Coverage-Bug: 261596770
Change-Id: Ied9787c1fa691d609ee7625433dc088d79d11473
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index da2c516..f669062 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -134,21 +134,22 @@
 
         @Nullable
         @Override
-        public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
-            if (info.callingPackage == null) {
+        public ActivityInterceptResult onInterceptActivityLaunch(@NonNull
+                ActivityInterceptorInfo info) {
+            if (info.getCallingPackage() == null) {
                 return null;
             }
-            PendingTrampoline pt = mPendingTrampolines.remove(info.callingPackage);
+            PendingTrampoline pt = mPendingTrampolines.remove(info.getCallingPackage());
             if (pt == null) {
                 return null;
             }
             pt.mResultReceiver.send(VirtualDeviceManager.LAUNCH_SUCCESS, null);
-            ActivityOptions options = info.checkedOptions;
+            ActivityOptions options = info.getCheckedOptions();
             if (options == null) {
                 options = ActivityOptions.makeBasic();
             }
             return new ActivityInterceptResult(
-                    info.intent, options.setLaunchDisplayId(pt.mDisplayId));
+                    info.getIntent(), options.setLaunchDisplayId(pt.mDisplayId));
         }
     };
 
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index b822541..68f79a2 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -147,7 +147,8 @@
             new ActivityInterceptorCallback() {
                 @Nullable
                 @Override
-                public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
+                public ActivityInterceptResult onInterceptActivityLaunch(@NonNull
+                        ActivityInterceptorInfo info) {
                     return null;
                 }
 
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index d6cac33..db44e14 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -1130,18 +1130,18 @@
                 new ActivityInterceptorCallback() {
                     @Nullable
                     @Override
-                    public ActivityInterceptorCallback.ActivityInterceptResult intercept(
-                            ActivityInterceptorInfo info) {
+                    public ActivityInterceptorCallback.ActivityInterceptResult
+                            onInterceptActivityLaunch(@NonNull ActivityInterceptorInfo info) {
                         return null;
                     }
 
                     @Override
                     public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo,
                             ActivityInterceptorInfo info) {
-                        super.onActivityLaunched(taskInfo, activityInfo, info);
                         if (!shouldShowNotificationDialogOrClearFlags(taskInfo,
-                                activityInfo.packageName, info.callingPackage, info.intent,
-                                info.checkedOptions, activityInfo.name, true)
+                                activityInfo.packageName, info.getCallingPackage(),
+                                info.getIntent(), info.getCheckedOptions(), activityInfo.name,
+                                true)
                                 || isNoDisplayActivity(activityInfo)) {
                             return;
                         }
@@ -1318,12 +1318,12 @@
                     ACTION_REQUEST_PERMISSIONS_FOR_OTHER);
             grantPermission.putExtra(Intent.EXTRA_PACKAGE_NAME, pkgName);
 
-            final boolean remoteAnimation = info != null && info.checkedOptions != null
-                    && info.checkedOptions.getAnimationType() == ANIM_REMOTE_ANIMATION
-                    && info.clearOptionsAnimation != null;
+            final boolean remoteAnimation = info != null && info.getCheckedOptions() != null
+                    && info.getCheckedOptions().getAnimationType() == ANIM_REMOTE_ANIMATION
+                    && info.getClearOptionsAnimationRunnable() != null;
             ActivityOptions options = remoteAnimation ? ActivityOptions.makeRemoteAnimation(
-                        info.checkedOptions.getRemoteAnimationAdapter(),
-                        info.checkedOptions.getRemoteTransition())
+                        info.getCheckedOptions().getRemoteAnimationAdapter(),
+                        info.getCheckedOptions().getRemoteTransition())
                     : new ActivityOptions(new Bundle());
             options.setTaskOverlay(true, false);
             options.setLaunchTaskId(taskId);
@@ -1333,7 +1333,7 @@
                 // animation from the intercepted activity and its siblings to prevent duplication.
                 // This should trigger ActivityRecord#clearOptionsAnimationForSiblings for the
                 // intercepted activity.
-                info.clearOptionsAnimation.run();
+                info.getClearOptionsAnimationRunnable().run();
             }
             try {
                 mContext.startActivityAsUser(grantPermission, options.toBundle(), user);
diff --git a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
index 48e6f97..c593fa3 100644
--- a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
+++ b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
@@ -31,119 +31,393 @@
 /**
  * Callback to intercept activity starts and possibly block/redirect them. The callback methods will
  * be called with the WindowManagerGlobalLock held.
+ * @hide
  */
-public abstract class ActivityInterceptorCallback {
+public interface ActivityInterceptorCallback {
     /**
-     * Intercept the launch intent based on various signals. If an interception happened, returns
-     * a new/existing non-null {@link ActivityInterceptResult} which may redirect to another
-     * activity or with new {@link ActivityOptions}.
+     * Called to allow intercepting activity launching based on the provided launch parameters and
+     * intent resolution.
      *
-     * @return null if no interception occurred, or a non-null result which replaces the existing
-     * intent and activity options.
+     * <p>If the interceptor decides to change the {@link Intent} or return different {@link
+     * ActivityOptions}, it should return a non-{@code null} {@link ActivityInterceptResult} which
+     * may redirect to another activity or use new {@link ActivityOptions}. Otherwise, the
+     * interceptor should return {@code null} to indicate that passed {@link Intent} should not be
+     * changed.
+     *
+     * @param info the information about the {@link Intent} that is being intercepted to launch an
+     *             {@link android.app.Activity}.
+     * @return {@code null} if the interceptor decides not to change the existing intent, or a non-
+     * {@code null} result which replaces the existing intent and activity options.
      */
-    public abstract @Nullable ActivityInterceptResult intercept(ActivityInterceptorInfo info);
+    @Nullable
+    ActivityInterceptResult onInterceptActivityLaunch(@NonNull ActivityInterceptorInfo info);
 
     /**
-     * Called when an activity is successfully launched. The intent included in the
-     * ActivityInterceptorInfo may have changed from the one sent in
-     * {@link #intercept(ActivityInterceptorInfo)}, due to the return from
-     * {@link #intercept(ActivityInterceptorInfo)}.
+     * Called when an activity is successfully launched.
+     *
+     * <p>The intent included in the ActivityInterceptorInfo may have changed from the one sent in
+     * {@link #onInterceptActivityLaunch(ActivityInterceptorInfo)}, due to the changes might applied
+     * during internception.
+     *
+     * <p>There is no callback in case that the {@link android.app.Activity} is failed to launch,
+     * and this is not necessary to be added for the known use-cases.
+     *
+     * @param taskInfo the information about the @{@link Task} holds the launched
+     *                 {@link android.app.Activity}.
+     * @param activityInfo the information about the launched {@link android.app.Activity}.
+     * @param info the information about the {@link Intent} after calling {@link
+     *             #onInterceptActivityLaunch(ActivityInterceptorInfo)}.
      */
-    public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo,
-            ActivityInterceptorInfo info) {
-    }
+    default void onActivityLaunched(@NonNull TaskInfo taskInfo, @NonNull ActivityInfo activityInfo,
+            @NonNull ActivityInterceptorInfo info) {}
 
     /**
-     * The unique id of each interceptor which determines the order it will execute in.
+     * The unique id of each interceptor registered by a system service which determines the order
+     * it will execute in.
+     * @hide
      */
     @IntDef(suffix = { "_ORDERED_ID" }, value = {
-            FIRST_ORDERED_ID,
+            // Order Ids for system services
+            SYSTEM_FIRST_ORDERED_ID,
             PERMISSION_POLICY_ORDERED_ID,
             VIRTUAL_DEVICE_SERVICE_ORDERED_ID,
             DREAM_MANAGER_ORDERED_ID,
-            LAST_ORDERED_ID // Update this when adding new ids
+            SYSTEM_LAST_ORDERED_ID, // Update this when adding new ids
+            // Order Ids for mainline module services
+            MAINLINE_FIRST_ORDERED_ID,
+            MAINLINE_SDK_SANDBOX_ORDER_ID,
+            MAINLINE_LAST_ORDERED_ID  // Update this when adding new mainline module ids
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface OrderedId {}
+    @interface OrderedId {}
 
     /**
      * The first id, used by the framework to determine the valid range of ids.
+     * @hide
      */
-    static final int FIRST_ORDERED_ID = 0;
+    int SYSTEM_FIRST_ORDERED_ID = 0;
 
     /**
      * The identifier for {@link com.android.server.policy.PermissionPolicyService} interceptor
+     * @hide
      */
-    public static final int PERMISSION_POLICY_ORDERED_ID = 1;
+    int PERMISSION_POLICY_ORDERED_ID = 1;
 
     /**
      * The identifier for {@link com.android.server.companion.virtual.VirtualDeviceManagerService}
      * interceptor.
+     * @hide
      */
-    public static final int VIRTUAL_DEVICE_SERVICE_ORDERED_ID = 3;
+    int VIRTUAL_DEVICE_SERVICE_ORDERED_ID = 3;
 
     /**
      * The identifier for {@link com.android.server.dreams.DreamManagerService} interceptor.
+     * @hide
      */
-    public static final int DREAM_MANAGER_ORDERED_ID = 4;
+    int DREAM_MANAGER_ORDERED_ID = 4;
 
     /**
      * The final id, used by the framework to determine the valid range of ids. Update this when
      * adding new ids.
+     * @hide
      */
-    static final int LAST_ORDERED_ID = DREAM_MANAGER_ORDERED_ID;
+    int SYSTEM_LAST_ORDERED_ID = DREAM_MANAGER_ORDERED_ID;
+
+    /**
+     * The first mainline module id, used by the framework to determine the valid range of ids
+     * could be used by mainline modules.
+     * @hide
+     */
+    int MAINLINE_FIRST_ORDERED_ID = 1000;
+
+    /**
+     * The identifier for {@link com.android.server.sdksandbox.SdkSandboxManagerService.Lifecycle}
+     * interceptor.
+     */
+    int MAINLINE_SDK_SANDBOX_ORDER_ID = 1001;
+
+    /**
+     * The final mainline module id, used by the framework to determine the valid range of ids
+     * could be used by mainline modules. Update this when adding new ids for mainline modules.
+     * @hide
+     */
+    int MAINLINE_LAST_ORDERED_ID = MAINLINE_SDK_SANDBOX_ORDER_ID;
+
+    /**
+     * Returns {@code true} if the id is in the range of valid system services including mainline
+     * module services.
+     * @hide
+     */
+    static boolean isValidOrderId(int id) {
+        return isValidMainlineOrderId(id)
+                || (id >= SYSTEM_FIRST_ORDERED_ID && id <= SYSTEM_LAST_ORDERED_ID);
+    }
+
+    /**
+     * Returns {@code true} if the id is in the range of valid mainline module services.
+     * @hide
+     */
+    static boolean isValidMainlineOrderId(int id) {
+        return id >= MAINLINE_FIRST_ORDERED_ID && id <= MAINLINE_LAST_ORDERED_ID;
+    }
 
     /**
      * Data class for storing the various arguments needed for activity interception.
+     * @hide
      */
-    public static final class ActivityInterceptorInfo {
-        public final int realCallingUid;
-        public final int realCallingPid;
-        public final int userId;
-        public final String callingPackage;
-        public final String callingFeatureId;
-        public final Intent intent;
-        public final ResolveInfo rInfo;
-        public final ActivityInfo aInfo;
-        public final String resolvedType;
-        public final int callingPid;
-        public final int callingUid;
-        public final ActivityOptions checkedOptions;
-        public final @Nullable Runnable clearOptionsAnimation;
+    final class ActivityInterceptorInfo {
+        private final int mCallingUid;
+        private final int mCallingPid;
+        private final int mRealCallingUid;
+        private final int mRealCallingPid;
+        private final int mUserId;
+        private final Intent mIntent;
+        @NonNull
+        private final ResolveInfo mResolveInfo;
+        @NonNull
+        private final ActivityInfo mActivityInfo;
+        @Nullable
+        private final String mResolvedType;
+        @Nullable
+        private final String mCallingPackage;
+        @Nullable
+        private final String mCallingFeatureId;
+        @Nullable
+        private final ActivityOptions mCheckedOptions;
+        @Nullable
+        private final Runnable mClearOptionsAnimation;
 
-        public ActivityInterceptorInfo(int realCallingUid, int realCallingPid, int userId,
-                String callingPackage, String callingFeatureId, Intent intent,
-                ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType, int callingPid,
-                int callingUid, ActivityOptions checkedOptions,
-                @Nullable Runnable clearOptionsAnimation) {
-            this.realCallingUid = realCallingUid;
-            this.realCallingPid = realCallingPid;
-            this.userId = userId;
-            this.callingPackage = callingPackage;
-            this.callingFeatureId = callingFeatureId;
-            this.intent = intent;
-            this.rInfo = rInfo;
-            this.aInfo = aInfo;
-            this.resolvedType = resolvedType;
-            this.callingPid = callingPid;
-            this.callingUid = callingUid;
-            this.checkedOptions = checkedOptions;
-            this.clearOptionsAnimation = clearOptionsAnimation;
+        /**
+         * @hide
+         */
+        public ActivityInterceptorInfo(Builder builder) {
+            this.mCallingUid = builder.mCallingUid;
+            this.mCallingPid = builder.mCallingPid;
+            this.mRealCallingUid = builder.mRealCallingUid;
+            this.mRealCallingPid = builder.mRealCallingPid;
+            this.mUserId = builder.mUserId;
+            this.mIntent = builder.mIntent;
+            this.mResolveInfo = builder.mResolveInfo;
+            this.mActivityInfo = builder.mActivityInfo;
+            this.mResolvedType = builder.mResolvedType;
+            this.mCallingPackage = builder.mCallingPackage;
+            this.mCallingFeatureId = builder.mCallingFeatureId;
+            this.mCheckedOptions = builder.mCheckedOptions;
+            this.mClearOptionsAnimation = builder.mClearOptionsAnimation;
+        }
+
+        /**
+         * Builder class to build instances of {@link ActivityInterceptorInfo}.
+         */
+        public static final class Builder {
+            private final int mCallingUid;
+            private final int mCallingPid;
+            private final int mRealCallingUid;
+            private final int mRealCallingPid;
+            private final int mUserId;
+            private final Intent mIntent;
+            @NonNull
+            private final ResolveInfo mResolveInfo;
+            @NonNull
+            private final ActivityInfo mActivityInfo;
+            @Nullable
+            private String mResolvedType;
+            @Nullable
+            private String mCallingPackage = null;
+            @Nullable
+            private String mCallingFeatureId = null;
+            @Nullable
+            private ActivityOptions mCheckedOptions = null;
+            @Nullable
+            private Runnable mClearOptionsAnimation = null;
+
+            /**
+             * Constructor of {@link ActivityInterceptorInfo.Builder}.
+             */
+            public Builder(int callingUid, int callingPid, int realCallingUid,
+                    int realCallingPid, int userId, @NonNull Intent intent,
+                    @NonNull ResolveInfo rInfo, @NonNull ActivityInfo aInfo) {
+                this.mCallingUid = callingUid;
+                this.mCallingPid = callingPid;
+                this.mRealCallingUid = realCallingUid;
+                this.mRealCallingPid = realCallingPid;
+                this.mUserId = userId;
+                this.mIntent = intent;
+                this.mResolveInfo = rInfo;
+                this.mActivityInfo = aInfo;
+            }
+
+            /**
+             * Returns a new instance of {@link ActivityInterceptorInfo} based on the {@link
+             * Builder} fields.
+             *
+             * @return a new instance of {@link ActivityInterceptorInfo}.
+             */
+            @NonNull
+            public ActivityInterceptorInfo build() {
+                return new ActivityInterceptorInfo(this);
+            }
+
+            /**
+             * Sets the value for the resolved type.
+             * @param resolvedType the resolved type.
+             */
+            @NonNull
+            public Builder setResolvedType(@NonNull String resolvedType) {
+                mResolvedType = resolvedType;
+                return this;
+            }
+
+            /**
+             * Sets the value for the calling package.
+             * @param callingPackage the calling package.
+             */
+            @NonNull
+            public Builder setCallingPackage(@NonNull String callingPackage) {
+                mCallingPackage = callingPackage;
+                return this;
+            }
+
+            /**
+             * Sets the value for the calling feature id.
+             * @param callingFeatureId the calling feature id.
+             */
+            @NonNull
+            public Builder setCallingFeatureId(@NonNull String callingFeatureId) {
+                mCallingFeatureId = callingFeatureId;
+                return this;
+            }
+
+            /**
+             * Sets the value for the {@link ActivityOptions}.
+             * @param checkedOptions the {@link ActivityOptions}.
+             */
+            @NonNull
+            public Builder setCheckedOptions(@NonNull ActivityOptions checkedOptions) {
+                mCheckedOptions = checkedOptions;
+                return this;
+            }
+
+            /**
+             * Sets the value for the {@link Runnable} object to clear options Animation.
+             * @param clearOptionsAnimationRunnable the calling package.
+             */
+            @NonNull
+            public Builder setClearOptionsAnimationRunnable(@NonNull
+                    Runnable clearOptionsAnimationRunnable) {
+                mClearOptionsAnimation = clearOptionsAnimationRunnable;
+                return this;
+            }
+        }
+
+        /** Returns the calling uid. */
+        public int getCallingUid() {
+            return mCallingUid;
+        }
+
+        /** Returns the calling pid. */
+        public int getCallingPid() {
+            return mCallingPid;
+        }
+
+        /** Returns the real calling uid. */
+        public int getRealCallingUid() {
+            return mRealCallingUid;
+        }
+
+        /** Returns the real calling pid. */
+        public int getRealCallingPid() {
+            return mRealCallingPid;
+        }
+
+        /** Returns the user id. */
+        public int getUserId() {
+            return mUserId;
+        }
+
+        /** Returns the {@link Intent}. */
+        @SuppressWarnings("IntentBuilderName")
+        @NonNull
+        public Intent getIntent() {
+            return mIntent;
+        }
+
+        /** Returns the {@link ResolveInfo}. */
+        @NonNull
+        public ResolveInfo getResolveInfo() {
+            return mResolveInfo;
+        }
+
+        /** Returns the {@link ActivityInfo}. */
+        @NonNull
+        public ActivityInfo getActivityInfo() {
+            return mActivityInfo;
+        }
+
+        /** Returns the real resolved type. */
+        @Nullable
+        public String getResolvedType() {
+            return mResolvedType;
+        }
+
+        /** Returns the calling package. */
+        @Nullable
+        public String getCallingPackage() {
+            return mCallingPackage;
+        }
+
+        /** Returns the calling feature id. */
+        @Nullable
+        public String getCallingFeatureId() {
+            return mCallingFeatureId;
+        }
+
+        /** Returns the {@link ActivityOptions}. */
+        @Nullable
+        public ActivityOptions getCheckedOptions() {
+            return mCheckedOptions;
+        }
+
+        /** Returns the {@link Runnable} object to clear options Animation. */
+        @Nullable
+        public Runnable getClearOptionsAnimationRunnable() {
+            return mClearOptionsAnimation;
         }
     }
 
     /**
      * Data class for storing the intercept result.
+     * @hide
      */
-    public static final class ActivityInterceptResult {
-        @NonNull public final Intent intent;
-        @NonNull public final ActivityOptions activityOptions;
+    final class ActivityInterceptResult {
+        @NonNull
+        private final Intent mIntent;
 
+        @NonNull
+        private final ActivityOptions mActivityOptions;
+
+        /** Generates the result of intercepting launching the {@link android.app.Activity}
+         *
+         * @param intent is the modified {@link Intent} after interception.
+         * @param activityOptions holds the {@link ActivityOptions} after interception.
+         */
         public ActivityInterceptResult(
-                @NonNull Intent intent,
-                @NonNull ActivityOptions activityOptions) {
-            this.intent = intent;
-            this.activityOptions = activityOptions;
+                @NonNull Intent intent, @NonNull ActivityOptions activityOptions) {
+            this.mIntent = intent;
+            this.mActivityOptions = activityOptions;
+        }
+
+        /** Returns the intercepted {@link Intent} */
+        @SuppressWarnings("IntentBuilderName")
+        @NonNull
+        public Intent getIntent() {
+            return mIntent;
+        }
+
+        /** Returns the intercepted {@link ActivityOptions} */
+        @NonNull
+        public ActivityOptions getActivityOptions() {
+            return mActivityOptions;
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 719f72c..84100a7 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -23,6 +23,7 @@
 import static android.app.PendingIntent.FLAG_ONE_SHOT;
 import static android.app.admin.DevicePolicyManager.EXTRA_RESTRICTION;
 import static android.app.admin.DevicePolicyManager.POLICY_SUSPEND_PACKAGES;
+import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_ACTIVITY;
 import static android.content.Context.KEYGUARD_SERVICE;
 import static android.content.Intent.EXTRA_INTENT;
 import static android.content.Intent.EXTRA_PACKAGE_NAME;
@@ -33,7 +34,9 @@
 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
 
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_SDK_SANDBOX_ORDER_ID;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.KeyguardManager;
@@ -226,13 +229,19 @@
                 getInterceptorInfo(null /* clearOptionsAnimation */);
 
         for (int i = 0; i < callbacks.size(); i++) {
+            final int orderId = callbacks.keyAt(i);
+            if (!shouldInterceptActivityLaunch(orderId, interceptorInfo)) {
+                continue;
+            }
+
             final ActivityInterceptorCallback callback = callbacks.valueAt(i);
-            final ActivityInterceptResult interceptResult = callback.intercept(interceptorInfo);
+            final ActivityInterceptResult interceptResult = callback.onInterceptActivityLaunch(
+                    interceptorInfo);
             if (interceptResult == null) {
                 continue;
             }
-            mIntent = interceptResult.intent;
-            mActivityOptions = interceptResult.activityOptions;
+            mIntent = interceptResult.getIntent();
+            mActivityOptions = interceptResult.getActivityOptions();
             mCallingPid = mRealCallingPid;
             mCallingUid = mRealCallingUid;
             mRInfo = mSupervisor.resolveIntent(mIntent, null, mUserId, 0, mRealCallingUid);
@@ -459,6 +468,11 @@
         ActivityInterceptorCallback.ActivityInterceptorInfo info = getInterceptorInfo(
                 r::clearOptionsAnimationForSiblings);
         for (int i = 0; i < callbacks.size(); i++) {
+            final int orderId = callbacks.keyAt(i);
+            if (!shouldNotifyOnActivityLaunch(orderId, info)) {
+                continue;
+            }
+
             final ActivityInterceptorCallback callback = callbacks.valueAt(i);
             callback.onActivityLaunched(taskInfo, r.info, info);
         }
@@ -466,9 +480,33 @@
 
     private ActivityInterceptorCallback.ActivityInterceptorInfo getInterceptorInfo(
             @Nullable Runnable clearOptionsAnimation) {
-        return new ActivityInterceptorCallback.ActivityInterceptorInfo(mRealCallingUid,
-                mRealCallingPid, mUserId, mCallingPackage, mCallingFeatureId, mIntent,
-                mRInfo, mAInfo, mResolvedType, mCallingPid, mCallingUid,
-                mActivityOptions, clearOptionsAnimation);
+        return new ActivityInterceptorCallback.ActivityInterceptorInfo.Builder(mCallingUid,
+                mCallingPid, mRealCallingUid, mRealCallingPid, mUserId, mIntent, mRInfo, mAInfo)
+                .setResolvedType(mResolvedType)
+                .setCallingPackage(mCallingPackage)
+                .setCallingFeatureId(mCallingFeatureId)
+                .setCheckedOptions(mActivityOptions)
+                .setClearOptionsAnimationRunnable(clearOptionsAnimation)
+                .build();
+    }
+
+    private boolean shouldInterceptActivityLaunch(
+            @ActivityInterceptorCallback.OrderedId int orderId,
+            @NonNull ActivityInterceptorCallback.ActivityInterceptorInfo info) {
+        if (orderId == MAINLINE_SDK_SANDBOX_ORDER_ID) {
+            return info.getIntent() != null && info.getIntent().getAction() != null
+                    && info.getIntent().getAction().equals(ACTION_START_SANDBOXED_ACTIVITY);
+        }
+        return true;
+    }
+
+    private boolean shouldNotifyOnActivityLaunch(
+            @ActivityInterceptorCallback.OrderedId int orderId,
+            @NonNull ActivityInterceptorCallback.ActivityInterceptorInfo info) {
+        if (orderId == MAINLINE_SDK_SANDBOX_ORDER_ID) {
+            return info.getIntent() != null && info.getIntent().getAction() != null
+                    && info.getIntent().getAction().equals(ACTION_START_SANDBOXED_ACTIVITY);
+        }
+        return true;
     }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index e475eb6..c2d4bfd 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -94,8 +94,10 @@
 import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
 import static com.android.server.am.EventLogTags.writeBootProgressEnableScreen;
 import static com.android.server.am.EventLogTags.writeConfigurationChanged;
-import static com.android.server.wm.ActivityInterceptorCallback.FIRST_ORDERED_ID;
-import static com.android.server.wm.ActivityInterceptorCallback.LAST_ORDERED_ID;
+import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_FIRST_ORDERED_ID;
+import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_LAST_ORDERED_ID;
+import static com.android.server.wm.ActivityInterceptorCallback.SYSTEM_FIRST_ORDERED_ID;
+import static com.android.server.wm.ActivityInterceptorCallback.SYSTEM_LAST_ORDERED_ID;
 import static com.android.server.wm.ActivityRecord.State.PAUSING;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ROOT_TASK;
@@ -6811,10 +6813,13 @@
                 if (mActivityInterceptorCallbacks.contains(id)) {
                     throw new IllegalArgumentException("Duplicate id provided: " + id);
                 }
-                if (id > LAST_ORDERED_ID || id < FIRST_ORDERED_ID) {
+                if (!ActivityInterceptorCallback.isValidOrderId(id)) {
                     throw new IllegalArgumentException(
-                            "Provided id " + id + " is not in range of valid ids ["
-                                    + FIRST_ORDERED_ID + "," + LAST_ORDERED_ID + "]");
+                            "Provided id " + id + " is not in range of valid ids for system "
+                                    + "services [" + SYSTEM_FIRST_ORDERED_ID + ","
+                                    + SYSTEM_LAST_ORDERED_ID + "] nor in range of valid ids for "
+                                    + "mainline module services [" + MAINLINE_FIRST_ORDERED_ID + ","
+                                    + MAINLINE_LAST_ORDERED_ID + "]");
                 }
                 mActivityInterceptorCallbacks.put(id, callback);
             }
diff --git a/services/core/java/com/android/server/wm/package-info.java b/services/core/java/com/android/server/wm/package-info.java
new file mode 100644
index 0000000..6ab5835
--- /dev/null
+++ b/services/core/java/com/android/server/wm/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @hide
+ * TODO(b/146466118) remove this javadoc tag
+ */
+@android.annotation.Hide
+package com.android.server.wm;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 8a15c30..b0461c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_ACTIVITY;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
 
@@ -25,6 +26,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_SDK_SANDBOX_ORDER_ID;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -33,7 +35,9 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
@@ -68,6 +72,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 /**
@@ -356,13 +361,14 @@
         int size = mActivityInterceptorCallbacks.size();
         mActivityInterceptorCallbacks.put(size, new ActivityInterceptorCallback() {
             @Override
-            public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
+            public ActivityInterceptResult onInterceptActivityLaunch(@NonNull
+                    ActivityInterceptorInfo info) {
                 if (intent == null && activityOptions == null) {
                     return null;
                 }
                 return new ActivityInterceptResult(
-                        intent != null ? intent : info.intent,
-                        activityOptions != null ? activityOptions : info.checkedOptions);
+                        intent != null ? intent : info.getIntent(),
+                        activityOptions != null ? activityOptions : info.getCheckedOptions());
             }
         });
     }
@@ -405,4 +411,30 @@
 
         verify(callback, times(1)).onActivityLaunched(any(), any(), any());
     }
+
+    @Test
+    public void testSandboxServiceInterceptionHappensToSandboxedActivityAction()
+            throws InterruptedException {
+
+        ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null);
+        mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback);
+
+        Intent intent = new Intent().setAction(ACTION_START_SANDBOXED_ACTIVITY);
+        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+
+        verify(spyCallback, times(1)).onInterceptActivityLaunch(
+                any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
+    }
+
+    @Test
+    public void testSandboxServiceInterceptionNotCalledForNotSandboxedActivityAction() {
+        ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null);
+        mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback);
+
+        Intent intent = new Intent();
+        mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+
+        verify(spyCallback, never()).onInterceptActivityLaunch(
+                any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 368b750..693d32e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -25,8 +25,9 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.server.wm.ActivityInterceptorCallback.FIRST_ORDERED_ID;
-import static com.android.server.wm.ActivityInterceptorCallback.LAST_ORDERED_ID;
+import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_FIRST_ORDERED_ID;
+import static com.android.server.wm.ActivityInterceptorCallback.SYSTEM_FIRST_ORDERED_ID;
+import static com.android.server.wm.ActivityInterceptorCallback.SYSTEM_LAST_ORDERED_ID;
 import static com.android.server.wm.ActivityRecord.State.PAUSED;
 import static com.android.server.wm.ActivityRecord.State.PAUSING;
 import static com.android.server.wm.ActivityRecord.State.RESUMED;
@@ -45,6 +46,7 @@
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.when;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -957,11 +959,12 @@
 
     @Test(expected = IllegalArgumentException.class)
     public void testRegisterActivityStartInterceptor_IndexTooSmall() {
-        mAtm.mInternal.registerActivityStartInterceptor(FIRST_ORDERED_ID - 1,
+        mAtm.mInternal.registerActivityStartInterceptor(SYSTEM_FIRST_ORDERED_ID - 1,
                 new ActivityInterceptorCallback() {
                     @Nullable
                     @Override
-                    public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
+                    public ActivityInterceptResult onInterceptActivityLaunch(
+                            @NonNull ActivityInterceptorInfo info) {
                         return null;
                     }
                 });
@@ -969,11 +972,12 @@
 
     @Test(expected = IllegalArgumentException.class)
     public void testRegisterActivityStartInterceptor_IndexTooLarge() {
-        mAtm.mInternal.registerActivityStartInterceptor(LAST_ORDERED_ID + 1,
+        mAtm.mInternal.registerActivityStartInterceptor(SYSTEM_LAST_ORDERED_ID + 1,
                 new ActivityInterceptorCallback() {
                     @Nullable
                     @Override
-                    public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
+                    public ActivityInterceptResult onInterceptActivityLaunch(
+                            @NonNull ActivityInterceptorInfo info) {
                         return null;
                     }
                 });
@@ -981,19 +985,21 @@
 
     @Test(expected = IllegalArgumentException.class)
     public void testRegisterActivityStartInterceptor_DuplicateId() {
-        mAtm.mInternal.registerActivityStartInterceptor(FIRST_ORDERED_ID,
+        mAtm.mInternal.registerActivityStartInterceptor(SYSTEM_FIRST_ORDERED_ID,
                 new ActivityInterceptorCallback() {
                     @Nullable
                     @Override
-                    public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
+                    public ActivityInterceptResult onInterceptActivityLaunch(
+                            @NonNull ActivityInterceptorInfo info) {
                         return null;
                     }
                 });
-        mAtm.mInternal.registerActivityStartInterceptor(FIRST_ORDERED_ID,
+        mAtm.mInternal.registerActivityStartInterceptor(SYSTEM_FIRST_ORDERED_ID,
                 new ActivityInterceptorCallback() {
                     @Nullable
                     @Override
-                    public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
+                    public ActivityInterceptResult onInterceptActivityLaunch(
+                            @NonNull ActivityInterceptorInfo info) {
                         return null;
                     }
                 });
@@ -1003,16 +1009,22 @@
     public void testRegisterActivityStartInterceptor() {
         assertEquals(0, mAtm.getActivityInterceptorCallbacks().size());
 
-        mAtm.mInternal.registerActivityStartInterceptor(FIRST_ORDERED_ID,
+        mAtm.mInternal.registerActivityStartInterceptor(SYSTEM_FIRST_ORDERED_ID,
                 new ActivityInterceptorCallback() {
                     @Nullable
                     @Override
-                    public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
+                    public ActivityInterceptResult onInterceptActivityLaunch(
+                            @NonNull ActivityInterceptorInfo info) {
                         return null;
                     }
                 });
 
         assertEquals(1, mAtm.getActivityInterceptorCallbacks().size());
-        assertTrue(mAtm.getActivityInterceptorCallbacks().contains(FIRST_ORDERED_ID));
+        assertTrue(mAtm.getActivityInterceptorCallbacks().contains(SYSTEM_FIRST_ORDERED_ID));
+    }
+
+    @Test
+    public void testSystemAndMainlineOrderIdsNotOverlapping() {
+        assertTrue(MAINLINE_FIRST_ORDERED_ID - SYSTEM_LAST_ORDERED_ID > 1);
     }
 }