Merge changes Ie4b018d9,I790ea567
* changes: Disable resolving while intercepting based on a flag Adding ActivityInterceptorCallbackRegistry
This commit is contained in:
committed by
Android (Google) Code Review
commit
09183fb168
@@ -169,3 +169,52 @@ package com.android.server.wifi {
|
||||
|
||||
}
|
||||
|
||||
package com.android.server.wm {
|
||||
|
||||
public interface ActivityInterceptorCallback {
|
||||
method public default void onActivityLaunched(@NonNull android.app.TaskInfo, @NonNull android.content.pm.ActivityInfo, @NonNull com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo);
|
||||
method @Nullable public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptResult onInterceptActivityLaunch(@NonNull com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo);
|
||||
field public static final int MAINLINE_SDK_SANDBOX_ORDER_ID = 1001; // 0x3e9
|
||||
}
|
||||
|
||||
public static final class ActivityInterceptorCallback.ActivityInterceptResult {
|
||||
ctor public ActivityInterceptorCallback.ActivityInterceptResult(@NonNull android.content.Intent, @NonNull android.app.ActivityOptions, boolean);
|
||||
method @NonNull public android.app.ActivityOptions getActivityOptions();
|
||||
method @NonNull public android.content.Intent getIntent();
|
||||
method public boolean isActivityResolved();
|
||||
}
|
||||
|
||||
public static final class ActivityInterceptorCallback.ActivityInterceptorInfo {
|
||||
method @NonNull public android.content.pm.ActivityInfo getActivityInfo();
|
||||
method @Nullable public String getCallingFeatureId();
|
||||
method @Nullable public String getCallingPackage();
|
||||
method public int getCallingPid();
|
||||
method public int getCallingUid();
|
||||
method @Nullable public android.app.ActivityOptions getCheckedOptions();
|
||||
method @Nullable public Runnable getClearOptionsAnimationRunnable();
|
||||
method @NonNull public android.content.Intent getIntent();
|
||||
method public int getRealCallingPid();
|
||||
method public int getRealCallingUid();
|
||||
method @NonNull public android.content.pm.ResolveInfo getResolveInfo();
|
||||
method @Nullable public String getResolvedType();
|
||||
method public int getUserId();
|
||||
}
|
||||
|
||||
public static final class ActivityInterceptorCallback.ActivityInterceptorInfo.Builder {
|
||||
ctor public ActivityInterceptorCallback.ActivityInterceptorInfo.Builder(int, int, int, int, int, @NonNull android.content.Intent, @NonNull android.content.pm.ResolveInfo, @NonNull android.content.pm.ActivityInfo);
|
||||
method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo build();
|
||||
method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setCallingFeatureId(@NonNull String);
|
||||
method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setCallingPackage(@NonNull String);
|
||||
method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setCheckedOptions(@NonNull android.app.ActivityOptions);
|
||||
method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setClearOptionsAnimationRunnable(@NonNull Runnable);
|
||||
method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setResolvedType(@NonNull String);
|
||||
}
|
||||
|
||||
public class ActivityInterceptorCallbackRegistry {
|
||||
method @NonNull public static com.android.server.wm.ActivityInterceptorCallbackRegistry getInstance();
|
||||
method public void registerActivityInterceptorCallback(int, @NonNull com.android.server.wm.ActivityInterceptorCallback);
|
||||
method public void unregisterActivityInterceptorCallback(int);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.wm;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.Intent;
|
||||
@@ -33,6 +34,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* be called with the WindowManagerGlobalLock held.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
|
||||
public interface ActivityInterceptorCallback {
|
||||
/**
|
||||
* Called to allow intercepting activity launching based on the provided launch parameters and
|
||||
@@ -165,6 +167,7 @@ public interface ActivityInterceptorCallback {
|
||||
* Data class for storing the various arguments needed for activity interception.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
|
||||
final class ActivityInterceptorInfo {
|
||||
private final int mCallingUid;
|
||||
private final int mCallingPid;
|
||||
@@ -389,6 +392,7 @@ public interface ActivityInterceptorCallback {
|
||||
* Data class for storing the intercept result.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
|
||||
final class ActivityInterceptResult {
|
||||
@NonNull
|
||||
private final Intent mIntent;
|
||||
@@ -396,15 +400,35 @@ public interface ActivityInterceptorCallback {
|
||||
@NonNull
|
||||
private final ActivityOptions mActivityOptions;
|
||||
|
||||
/** Generates the result of intercepting launching the {@link android.app.Activity}
|
||||
private final boolean mActivityResolved;
|
||||
|
||||
/**
|
||||
* This constructor should only be used if both {@link ActivityInfo} and {@link ResolveInfo}
|
||||
* did not get resolved while interception.
|
||||
* @hide
|
||||
*/
|
||||
public ActivityInterceptResult(@NonNull Intent intent,
|
||||
@NonNull ActivityOptions activityOptions) {
|
||||
this(intent, activityOptions, false /* activityResolved */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the result of intercepting launching the {@link android.app.Activity}
|
||||
*
|
||||
* <p>Interceptor should return non-{@code null} result when {@link
|
||||
* #onInterceptActivityLaunch(ActivityInterceptorInfo)} gets called as an indicator that
|
||||
* interception has happened.
|
||||
*
|
||||
* @param intent is the modified {@link Intent} after interception.
|
||||
* @param activityOptions holds the {@link ActivityOptions} after interception.
|
||||
* @param activityResolved should be {@code true} only if {@link ActivityInfo} or {@link
|
||||
* ResolveInfo} gets resolved, otherwise should be {@code false}.
|
||||
*/
|
||||
public ActivityInterceptResult(
|
||||
@NonNull Intent intent, @NonNull ActivityOptions activityOptions) {
|
||||
public ActivityInterceptResult(@NonNull Intent intent,
|
||||
@NonNull ActivityOptions activityOptions, boolean activityResolved) {
|
||||
this.mIntent = intent;
|
||||
this.mActivityOptions = activityOptions;
|
||||
this.mActivityResolved = activityResolved;
|
||||
}
|
||||
|
||||
/** Returns the intercepted {@link Intent} */
|
||||
@@ -419,5 +443,12 @@ public interface ActivityInterceptorCallback {
|
||||
public ActivityOptions getActivityOptions() {
|
||||
return mActivityOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the {@link ActivityInfo} or {@link ResolveInfo} gets resolved.
|
||||
*/
|
||||
public boolean isActivityResolved() {
|
||||
return mActivityResolved;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Binder;
|
||||
import android.os.Process;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
/**
|
||||
* This class should be used by system services which are part of mainline modules to register
|
||||
* {@link ActivityInterceptorCallback}. For other system services, this function should be used
|
||||
* instead {@link ActivityTaskManagerInternal#registerActivityStartInterceptor(
|
||||
* int, ActivityInterceptorCallback)}.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
|
||||
public class ActivityInterceptorCallbackRegistry {
|
||||
|
||||
private static final ActivityInterceptorCallbackRegistry sInstance =
|
||||
new ActivityInterceptorCallbackRegistry();
|
||||
|
||||
private ActivityInterceptorCallbackRegistry() {}
|
||||
|
||||
/** Returns an already initialised singleton instance of this class. */
|
||||
@NonNull
|
||||
public static ActivityInterceptorCallbackRegistry getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback which can intercept activity launching flow.
|
||||
*
|
||||
* <p>Only system services which are part of mainline modules should call this function.
|
||||
*
|
||||
* <p>To avoid Activity launch delays, the callbacks must execute quickly and avoid acquiring
|
||||
* other system process locks.
|
||||
*
|
||||
* @param mainlineOrderId has to be one of the following [{@link
|
||||
* ActivityInterceptorCallback#MAINLINE_FIRST_ORDERED_ID}].
|
||||
* @param callback the {@link ActivityInterceptorCallback} to register.
|
||||
* @throws IllegalArgumentException if duplicate ids are provided, the provided id is not the
|
||||
* mainline module range or the provided {@code callback} is null.
|
||||
*/
|
||||
// ExecutorRegistration is suppressed as the callback is called synchronously in the system
|
||||
// server.
|
||||
@SuppressWarnings("ExecutorRegistration")
|
||||
public void registerActivityInterceptorCallback(
|
||||
@ActivityInterceptorCallback.OrderedId int mainlineOrderId,
|
||||
@NonNull ActivityInterceptorCallback callback) {
|
||||
if (getCallingUid() != Process.SYSTEM_UID) {
|
||||
throw new SecurityException("Only system server can register "
|
||||
+ "ActivityInterceptorCallback");
|
||||
}
|
||||
if (!ActivityInterceptorCallback.isValidMainlineOrderId(mainlineOrderId)) {
|
||||
throw new IllegalArgumentException("id is not in the mainline modules range, please use"
|
||||
+ "ActivityTaskManagerInternal.registerActivityStartInterceptor(OrderedId, "
|
||||
+ "ActivityInterceptorCallback) instead.");
|
||||
}
|
||||
if (callback == null) {
|
||||
throw new IllegalArgumentException("The passed ActivityInterceptorCallback can not be "
|
||||
+ "null");
|
||||
}
|
||||
ActivityTaskManagerInternal activityTaskManagerInternal =
|
||||
LocalServices.getService(ActivityTaskManagerInternal.class);
|
||||
activityTaskManagerInternal.registerActivityStartInterceptor(mainlineOrderId, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters an already registered {@link ActivityInterceptorCallback}.
|
||||
*
|
||||
* @param mainlineOrderId the order id of the {@link ActivityInterceptorCallback} should be
|
||||
* unregistered, this callback should be registered before by calling
|
||||
* {@link #registerActivityInterceptorCallback(int,
|
||||
* ActivityInterceptorCallback)} using the same order id.
|
||||
* @throws IllegalArgumentException if the provided id is not the mainline module range or is
|
||||
* not registered
|
||||
*/
|
||||
public void unregisterActivityInterceptorCallback(
|
||||
@ActivityInterceptorCallback.OrderedId int mainlineOrderId) {
|
||||
if (getCallingUid() != Process.SYSTEM_UID) {
|
||||
throw new SecurityException("Only system server can register "
|
||||
+ "ActivityInterceptorCallback");
|
||||
}
|
||||
if (!ActivityInterceptorCallback.isValidMainlineOrderId(mainlineOrderId)) {
|
||||
throw new IllegalArgumentException("id is not in the mainline modules range, please use"
|
||||
+ "ActivityTaskManagerInternal.unregisterActivityStartInterceptor(OrderedId) "
|
||||
+ "instead.");
|
||||
}
|
||||
ActivityTaskManagerInternal activityTaskManagerInternal =
|
||||
LocalServices.getService(ActivityTaskManagerInternal.class);
|
||||
activityTaskManagerInternal.unregisterActivityStartInterceptor(mainlineOrderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* This hidden function is for unit tests as a way to behave like as if they are called from
|
||||
* system server process uid by mocking it and returning {@link Process#SYSTEM_UID}.
|
||||
* Do not make this {@code public} to apps as apps should not have a way to change the uid.
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
int getCallingUid() {
|
||||
return Binder.getCallingUid();
|
||||
}
|
||||
}
|
||||
@@ -244,6 +244,9 @@ class ActivityStartInterceptor {
|
||||
mActivityOptions = interceptResult.getActivityOptions();
|
||||
mCallingPid = mRealCallingPid;
|
||||
mCallingUid = mRealCallingUid;
|
||||
if (interceptResult.isActivityResolved()) {
|
||||
return true;
|
||||
}
|
||||
mRInfo = mSupervisor.resolveIntent(mIntent, null, mUserId, 0, mRealCallingUid);
|
||||
mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
|
||||
null /*profilerInfo*/);
|
||||
|
||||
@@ -680,12 +680,23 @@ public abstract class ActivityTaskManagerInternal {
|
||||
|
||||
/**
|
||||
* Registers a callback which can intercept activity starts.
|
||||
* @throws IllegalArgumentException if duplicate ids are provided
|
||||
* @throws IllegalArgumentException if duplicate ids are provided or the provided {@code
|
||||
* callback} is null
|
||||
* @see ActivityInterceptorCallbackRegistry
|
||||
* #registerActivityInterceptorCallback(int, ActivityInterceptorCallback)
|
||||
*/
|
||||
public abstract void registerActivityStartInterceptor(
|
||||
@ActivityInterceptorCallback.OrderedId int id,
|
||||
ActivityInterceptorCallback callback);
|
||||
|
||||
/**
|
||||
* Unregisters an {@link ActivityInterceptorCallback}.
|
||||
* @throws IllegalArgumentException if id is not registered
|
||||
* @see ActivityInterceptorCallbackRegistry#unregisterActivityInterceptorCallback(int)
|
||||
*/
|
||||
public abstract void unregisterActivityStartInterceptor(
|
||||
@ActivityInterceptorCallback.OrderedId int id);
|
||||
|
||||
/** Get the most recent task excluding the first running task (the one on the front most). */
|
||||
public abstract ActivityManager.RecentTaskInfo getMostRecentTaskFromBackground();
|
||||
|
||||
|
||||
@@ -6801,6 +6801,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
if (mActivityInterceptorCallbacks.contains(id)) {
|
||||
throw new IllegalArgumentException("Duplicate id provided: " + id);
|
||||
}
|
||||
if (callback == null) {
|
||||
throw new IllegalArgumentException("The passed ActivityInterceptorCallback "
|
||||
+ "can not be null");
|
||||
}
|
||||
if (!ActivityInterceptorCallback.isValidOrderId(id)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Provided id " + id + " is not in range of valid ids for system "
|
||||
@@ -6813,6 +6817,18 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterActivityStartInterceptor(
|
||||
@ActivityInterceptorCallback.OrderedId int id) {
|
||||
synchronized (mGlobalLock) {
|
||||
if (!mActivityInterceptorCallbacks.contains(id)) {
|
||||
throw new IllegalArgumentException(
|
||||
"ActivityInterceptorCallback with id (" + id + ") is not registered");
|
||||
}
|
||||
mActivityInterceptorCallbacks.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityManager.RecentTaskInfo getMostRecentTaskFromBackground() {
|
||||
List<ActivityManager.RunningTaskInfo> runningTaskInfoList = getTasks(1);
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_FIRST_ORDERED_ID;
|
||||
import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_LAST_ORDERED_ID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.os.Process;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.MediumTest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/**
|
||||
* Tests for the {@link ActivityInterceptorCallbackRegistry} class.
|
||||
*/
|
||||
@Presubmit
|
||||
@MediumTest
|
||||
@RunWith(WindowTestRunner.class)
|
||||
public final class ActivityInterceptorCallbackRegistryTest extends WindowTestsBase {
|
||||
|
||||
private ActivityInterceptorCallbackRegistry mRegistry;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mRegistry = spy(ActivityInterceptorCallbackRegistry.getInstance());
|
||||
Mockito.doReturn(Process.SYSTEM_UID).when(mRegistry).getCallingUid();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerActivityInterceptorCallbackFailIfNotSystemId() {
|
||||
// default registry with test app uid
|
||||
ActivityInterceptorCallbackRegistry registry = spy(
|
||||
ActivityInterceptorCallbackRegistry.getInstance());
|
||||
assertThrows(
|
||||
SecurityException.class,
|
||||
() -> registry.registerActivityInterceptorCallback(MAINLINE_LAST_ORDERED_ID + 1,
|
||||
info -> null)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerActivityInterceptorCallbackFailIfIdNotInRange() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> mRegistry.registerActivityInterceptorCallback(MAINLINE_LAST_ORDERED_ID + 1,
|
||||
info -> null)
|
||||
);
|
||||
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> mRegistry.registerActivityInterceptorCallback(MAINLINE_FIRST_ORDERED_ID - 1,
|
||||
info -> null)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerActivityInterceptorCallbackFailIfCallbackIsNull() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> mRegistry.registerActivityInterceptorCallback(MAINLINE_FIRST_ORDERED_ID,
|
||||
null)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerActivityInterceptorCallbackSuccessfully() {
|
||||
int size = mAtm.getActivityInterceptorCallbacks().size();
|
||||
int orderId = MAINLINE_FIRST_ORDERED_ID;
|
||||
mRegistry.registerActivityInterceptorCallback(orderId,
|
||||
info -> null);
|
||||
assertEquals(size + 1, mAtm.getActivityInterceptorCallbacks().size());
|
||||
assertTrue(mAtm.getActivityInterceptorCallbacks().contains(orderId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregisterActivityInterceptorCallbackFailIfNotSystemId() {
|
||||
// default registry with test app uid
|
||||
ActivityInterceptorCallbackRegistry registry = spy(
|
||||
ActivityInterceptorCallbackRegistry.getInstance());
|
||||
assertThrows(
|
||||
SecurityException.class,
|
||||
() -> registry.unregisterActivityInterceptorCallback(MAINLINE_LAST_ORDERED_ID + 1)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unRegisterActivityInterceptorCallbackFailIfIdNotInRange() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> mRegistry.unregisterActivityInterceptorCallback(
|
||||
MAINLINE_LAST_ORDERED_ID + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregisterActivityInterceptorCallbackFailIfNotRegistered() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> mRegistry.unregisterActivityInterceptorCallback(MAINLINE_FIRST_ORDERED_ID)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregisterActivityInterceptorCallbackSuccessfully() {
|
||||
int size = mAtm.getActivityInterceptorCallbacks().size();
|
||||
int orderId = MAINLINE_FIRST_ORDERED_ID;
|
||||
mRegistry.registerActivityInterceptorCallback(orderId,
|
||||
info -> null);
|
||||
assertEquals(size + 1, mAtm.getActivityInterceptorCallbacks().size());
|
||||
assertTrue(mAtm.getActivityInterceptorCallbacks().contains(orderId));
|
||||
|
||||
mRegistry.unregisterActivityInterceptorCallback(orderId);
|
||||
assertEquals(size, mAtm.getActivityInterceptorCallbacks().size());
|
||||
assertFalse(mAtm.getActivityInterceptorCallbacks().contains(orderId));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_SDK_SAN
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -358,6 +359,12 @@ public class ActivityStartInterceptorTest {
|
||||
|
||||
public void addMockInterceptorCallback(
|
||||
@Nullable Intent intent, @Nullable ActivityOptions activityOptions) {
|
||||
addMockInterceptorCallback(intent, activityOptions, false);
|
||||
}
|
||||
|
||||
public void addMockInterceptorCallback(
|
||||
@Nullable Intent intent, @Nullable ActivityOptions activityOptions,
|
||||
boolean skipResolving) {
|
||||
int size = mActivityInterceptorCallbacks.size();
|
||||
mActivityInterceptorCallbacks.put(size, new ActivityInterceptorCallback() {
|
||||
@Override
|
||||
@@ -368,7 +375,8 @@ public class ActivityStartInterceptorTest {
|
||||
}
|
||||
return new ActivityInterceptResult(
|
||||
intent != null ? intent : info.getIntent(),
|
||||
activityOptions != null ? activityOptions : info.getCheckedOptions());
|
||||
activityOptions != null ? activityOptions : info.getCheckedOptions(),
|
||||
skipResolving);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -400,6 +408,30 @@ public class ActivityStartInterceptorTest {
|
||||
assertEquals("android.test.second", mInterceptor.mIntent.getAction());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptionCallback_skipResolving() {
|
||||
addMockInterceptorCallback(
|
||||
new Intent("android.test.foo"),
|
||||
ActivityOptions.makeBasic().setLaunchDisplayId(3), true);
|
||||
ActivityInfo aInfo = mAInfo;
|
||||
assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null));
|
||||
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
|
||||
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
|
||||
assertEquals(aInfo, mInterceptor.mAInfo); // mAInfo should not be resolved
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptionCallback_NoSkipResolving() throws InterruptedException {
|
||||
addMockInterceptorCallback(
|
||||
new Intent("android.test.foo"),
|
||||
ActivityOptions.makeBasic().setLaunchDisplayId(3));
|
||||
ActivityInfo aInfo = mAInfo;
|
||||
assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null));
|
||||
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
|
||||
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
|
||||
assertNotEquals(aInfo, mInterceptor.mAInfo); // mAInfo should be resolved after intercept
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActivityLaunchedCallback_singleCallback() {
|
||||
addMockInterceptorCallback(null, null);
|
||||
|
||||
@@ -1027,4 +1027,25 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
|
||||
public void testSystemAndMainlineOrderIdsNotOverlapping() {
|
||||
assertTrue(MAINLINE_FIRST_ORDERED_ID - SYSTEM_LAST_ORDERED_ID > 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisterActivityStartInterceptor() {
|
||||
int size = mAtm.getActivityInterceptorCallbacks().size();
|
||||
int orderId = SYSTEM_FIRST_ORDERED_ID;
|
||||
|
||||
mAtm.mInternal.registerActivityStartInterceptor(orderId,
|
||||
(ActivityInterceptorCallback) info -> null);
|
||||
assertEquals(size + 1, mAtm.getActivityInterceptorCallbacks().size());
|
||||
assertTrue(mAtm.getActivityInterceptorCallbacks().contains(orderId));
|
||||
|
||||
mAtm.mInternal.unregisterActivityStartInterceptor(orderId);
|
||||
assertEquals(size, mAtm.getActivityInterceptorCallbacks().size());
|
||||
assertFalse(mAtm.getActivityInterceptorCallbacks().contains(orderId));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testUnregisterActivityStartInterceptor_IdNotExist() {
|
||||
assertEquals(0, mAtm.getActivityInterceptorCallbacks().size());
|
||||
mAtm.mInternal.unregisterActivityStartInterceptor(SYSTEM_FIRST_ORDERED_ID);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user