diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 154068eb9e092..74a69a6237905 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -16,6 +16,7 @@ package android.content; +import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_ACTIVITY; import static android.content.ContentProvider.maybeAddUserId; import android.Manifest; @@ -12463,4 +12464,19 @@ public class Intent implements Parcelable, Cloneable { public boolean isDocument() { return (mFlags & FLAG_ACTIVITY_NEW_DOCUMENT) == FLAG_ACTIVITY_NEW_DOCUMENT; } + + /** @hide */ + public boolean isSandboxActivity(@NonNull Context context) { + if (mAction != null && mAction.equals(ACTION_START_SANDBOXED_ACTIVITY)) { + return true; + } + final String sandboxPackageName = context.getPackageManager().getSdkSandboxPackageName(); + if (mPackage != null && mPackage.equals(sandboxPackageName)) { + return true; + } + if (mComponent != null && mComponent.getPackageName().equals(sandboxPackageName)) { + return true; + } + return false; + } } diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java index 1944b3f8e6d3b..90af4c6236aa3 100644 --- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java +++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java @@ -23,7 +23,6 @@ import static android.app.PendingIntent.FLAG_IMMUTABLE; 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; @@ -503,8 +502,7 @@ class ActivityStartInterceptor { @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 info.getIntent() != null && info.getIntent().isSandboxActivity(mServiceContext); } return true; } @@ -513,8 +511,7 @@ class ActivityStartInterceptor { @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 info.getIntent() != null && info.getIntent().isSandboxActivity(mServiceContext); } 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 401c16f7f76ac..abf66bc7ccc03 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -38,7 +38,6 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_ACTIVITY; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; @@ -1244,9 +1243,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { assertPackageMatchesCallingUid(callingPackage); enforceNotIsolatedCaller("startActivityAsUser"); - boolean isSandboxedActivity = (intent != null && intent.getAction() != null - && intent.getAction().equals(ACTION_START_SANDBOXED_ACTIVITY)); - if (isSandboxedActivity) { + if (intent != null && intent.isSandboxActivity(mContext)) { SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager( SdkSandboxManagerLocal.class); sdkSandboxManagerLocal.enforceAllowedToHostSandboxedActivity( 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 7d16fb2e02554..4890f3e6cbf15 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java @@ -44,11 +44,13 @@ import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.KeyguardManager; import android.app.admin.DevicePolicyManagerInternal; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; +import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; @@ -445,12 +447,15 @@ public class ActivityStartInterceptorTest { } @Test - public void testSandboxServiceInterceptionHappensToSandboxedActivityAction() - throws InterruptedException { - + public void testSandboxServiceInterceptionHappensToIntentWithSandboxActivityAction() { ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null); mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback); + PackageManager packageManagerMock = mock(PackageManager.class); + String sandboxPackageNameMock = "com.sandbox.mock"; + when(mContext.getPackageManager()).thenReturn(packageManagerMock); + when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock); + Intent intent = new Intent().setAction(ACTION_START_SANDBOXED_ACTIVITY); mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null); @@ -459,13 +464,68 @@ public class ActivityStartInterceptorTest { } @Test - public void testSandboxServiceInterceptionNotCalledForNotSandboxedActivityAction() { + public void testSandboxServiceInterceptionHappensToIntentWithSandboxPackage() { ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null); mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback); + PackageManager packageManagerMock = mock(PackageManager.class); + String sandboxPackageNameMock = "com.sandbox.mock"; + when(mContext.getPackageManager()).thenReturn(packageManagerMock); + when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock); + + Intent intent = new Intent().setPackage(sandboxPackageNameMock); + mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null); + + verify(spyCallback, times(1)).onInterceptActivityLaunch( + any(ActivityInterceptorCallback.ActivityInterceptorInfo.class)); + } + + @Test + public void testSandboxServiceInterceptionHappensToIntentWithComponentNameWithSandboxPackage() { + ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null); + mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback); + + PackageManager packageManagerMock = mock(PackageManager.class); + String sandboxPackageNameMock = "com.sandbox.mock"; + when(mContext.getPackageManager()).thenReturn(packageManagerMock); + when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock); + + Intent intent = new Intent().setComponent(new ComponentName(sandboxPackageNameMock, "")); + mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null); + + verify(spyCallback, times(1)).onInterceptActivityLaunch( + any(ActivityInterceptorCallback.ActivityInterceptorInfo.class)); + } + + @Test + public void testSandboxServiceInterceptionNotCalledWhenIntentNotRelatedToSandbox() { + ActivityInterceptorCallback spyCallback = Mockito.spy(info -> null); + mActivityInterceptorCallbacks.put(MAINLINE_SDK_SANDBOX_ORDER_ID, spyCallback); + + PackageManager packageManagerMock = mock(PackageManager.class); + String sandboxPackageNameMock = "com.sandbox.mock"; + when(mContext.getPackageManager()).thenReturn(packageManagerMock); + when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock); + + // Intent: null + mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null); + + // Action: null, Package: null, ComponentName: null Intent intent = new Intent(); mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null); + // Wrong Action + intent = new Intent().setAction(Intent.ACTION_VIEW); + mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null); + + // Wrong Package + intent = new Intent().setPackage("Random"); + mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null); + + // Wrong ComponentName's package + intent = new Intent().setComponent(new ComponentName("Random", "")); + mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null); + verify(spyCallback, never()).onInterceptActivityLaunch( any(ActivityInterceptorCallback.ActivityInterceptorInfo.class)); }