Merge "Add internal WM API for registering activity interceptors." into sc-v2-dev
This commit is contained in:
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.IntDef;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.app.ActivityOptions;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to intercept activity starts and possibly block/redirect them.
|
||||||
|
*/
|
||||||
|
public abstract class ActivityInterceptorCallback {
|
||||||
|
/**
|
||||||
|
* Intercept the launch intent based on various signals. If an interception happened, returns
|
||||||
|
* a new/existing non-null {@link Intent} which may redirect to another activity.
|
||||||
|
*
|
||||||
|
* @return null if no interception occurred, or a non-null intent which replaces the
|
||||||
|
* existing intent.
|
||||||
|
*/
|
||||||
|
public abstract @Nullable Intent intercept(ActivityInterceptorInfo info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unique id of each interceptor which determines the order it will execute in.
|
||||||
|
*/
|
||||||
|
@IntDef(suffix = { "_ORDERED_ID" }, value = {
|
||||||
|
FIRST_ORDERED_ID,
|
||||||
|
LAST_ORDERED_ID // Update this when adding new ids
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface OrderedId {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first id, used by the framework to determine the valid range of ids.
|
||||||
|
*/
|
||||||
|
static final int FIRST_ORDERED_ID = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The final id, used by the framework to determine the valid range of ids. Update this when
|
||||||
|
* adding new ids.
|
||||||
|
*/
|
||||||
|
static final int LAST_ORDERED_ID = FIRST_ORDERED_ID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data class for storing the various arguments needed for activity interception.
|
||||||
|
*/
|
||||||
|
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 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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@ import android.os.Bundle;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.app.BlockedAppActivity;
|
import com.android.internal.app.BlockedAppActivity;
|
||||||
@@ -178,7 +179,33 @@ class ActivityStartInterceptor {
|
|||||||
// before issuing the work challenge.
|
// before issuing the work challenge.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return interceptLockedManagedProfileIfNeeded();
|
if (interceptLockedManagedProfileIfNeeded()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final SparseArray<ActivityInterceptorCallback> callbacks =
|
||||||
|
mService.getActivityInterceptorCallbacks();
|
||||||
|
final ActivityInterceptorCallback.ActivityInterceptorInfo interceptorInfo =
|
||||||
|
new ActivityInterceptorCallback.ActivityInterceptorInfo(mRealCallingUid,
|
||||||
|
mRealCallingPid, mUserId, mCallingPackage, mCallingFeatureId, mIntent,
|
||||||
|
mRInfo, mAInfo, mResolvedType, mCallingPid, mCallingUid,
|
||||||
|
mActivityOptions);
|
||||||
|
|
||||||
|
for (int i = 0; i < callbacks.size(); i++) {
|
||||||
|
final ActivityInterceptorCallback callback = callbacks.valueAt(i);
|
||||||
|
final Intent newIntent = callback.intercept(interceptorInfo);
|
||||||
|
if (newIntent == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mIntent = newIntent;
|
||||||
|
mCallingPid = mRealCallingPid;
|
||||||
|
mCallingUid = mRealCallingUid;
|
||||||
|
mRInfo = mSupervisor.resolveIntent(mIntent, null, mUserId, 0, mRealCallingUid);
|
||||||
|
mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
|
||||||
|
null /*profilerInfo*/);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasCrossProfileAnimation() {
|
private boolean hasCrossProfileAnimation() {
|
||||||
|
|||||||
@@ -678,4 +678,12 @@ public abstract class ActivityTaskManagerInternal {
|
|||||||
|
|
||||||
/** Called when the device is waking up */
|
/** Called when the device is waking up */
|
||||||
public abstract void notifyWakingUp();
|
public abstract void notifyWakingUp();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a callback which can intercept activity starts.
|
||||||
|
* @throws IllegalArgumentException if duplicate ids are provided
|
||||||
|
*/
|
||||||
|
public abstract void registerActivityStartInterceptor(
|
||||||
|
@ActivityInterceptorCallback.OrderedId int id,
|
||||||
|
ActivityInterceptorCallback callback);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.Scr
|
|||||||
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
|
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
|
||||||
import static com.android.server.am.EventLogTags.writeBootProgressEnableScreen;
|
import static com.android.server.am.EventLogTags.writeBootProgressEnableScreen;
|
||||||
import static com.android.server.am.EventLogTags.writeConfigurationChanged;
|
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.ActivityTaskManagerDebugConfig.DEBUG_ALL;
|
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
|
||||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ROOT_TASK;
|
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ROOT_TASK;
|
||||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
|
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
|
||||||
@@ -458,6 +460,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
/** The controller for all operations related to locktask. */
|
/** The controller for all operations related to locktask. */
|
||||||
private LockTaskController mLockTaskController;
|
private LockTaskController mLockTaskController;
|
||||||
private ActivityStartController mActivityStartController;
|
private ActivityStartController mActivityStartController;
|
||||||
|
private SparseArray<ActivityInterceptorCallback> mActivityInterceptorCallbacks =
|
||||||
|
new SparseArray<>();
|
||||||
PackageConfigPersister mPackageConfigPersister;
|
PackageConfigPersister mPackageConfigPersister;
|
||||||
|
|
||||||
boolean mSuppressResizeConfigChanges;
|
boolean mSuppressResizeConfigChanges;
|
||||||
@@ -1115,6 +1119,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
return mBackgroundActivityStartCallback;
|
return mBackgroundActivityStartCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SparseArray<ActivityInterceptorCallback> getActivityInterceptorCallbacks() {
|
||||||
|
return mActivityInterceptorCallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
private void start() {
|
private void start() {
|
||||||
LocalServices.addService(ActivityTaskManagerInternal.class, mInternal);
|
LocalServices.addService(ActivityTaskManagerInternal.class, mInternal);
|
||||||
}
|
}
|
||||||
@@ -4738,7 +4746,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
mContext.getText(R.string.heavy_weight_notification_detail))
|
mContext.getText(R.string.heavy_weight_notification_detail))
|
||||||
.setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
|
.setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
|
||||||
intent, PendingIntent.FLAG_CANCEL_CURRENT
|
intent, PendingIntent.FLAG_CANCEL_CURRENT
|
||||||
| PendingIntent.FLAG_IMMUTABLE, null,
|
| PendingIntent.FLAG_IMMUTABLE, null,
|
||||||
new UserHandle(userId)))
|
new UserHandle(userId)))
|
||||||
.build();
|
.build();
|
||||||
try {
|
try {
|
||||||
@@ -6583,5 +6591,22 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
getTransitionController().requestTransitionIfNeeded(TRANSIT_WAKE, 0 /* flags */,
|
getTransitionController().requestTransitionIfNeeded(TRANSIT_WAKE, 0 /* flags */,
|
||||||
null /* trigger */, mRootWindowContainer.getDefaultDisplay());
|
null /* trigger */, mRootWindowContainer.getDefaultDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerActivityStartInterceptor(
|
||||||
|
@ActivityInterceptorCallback.OrderedId int id,
|
||||||
|
ActivityInterceptorCallback callback) {
|
||||||
|
synchronized (mGlobalLock) {
|
||||||
|
if (mActivityInterceptorCallbacks.contains(id)) {
|
||||||
|
throw new IllegalArgumentException("Duplicate id provided: " + id);
|
||||||
|
}
|
||||||
|
if (id > LAST_ORDERED_ID || id < FIRST_ORDERED_ID) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Provided id " + id + " is not in range of valid ids ["
|
||||||
|
+ FIRST_ORDERED_ID + "," + LAST_ORDERED_ID + "]");
|
||||||
|
}
|
||||||
|
mActivityInterceptorCallbacks.put(id, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.nullable;
|
import static org.mockito.ArgumentMatchers.nullable;
|
||||||
|
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManagerInternal;
|
import android.app.ActivityManagerInternal;
|
||||||
import android.app.KeyguardManager;
|
import android.app.KeyguardManager;
|
||||||
import android.app.admin.DevicePolicyManagerInternal;
|
import android.app.admin.DevicePolicyManagerInternal;
|
||||||
@@ -42,6 +43,7 @@ import android.os.UserHandle;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.testing.DexmakerShareClassLoaderRule;
|
import android.testing.DexmakerShareClassLoaderRule;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
* Unit tests for {@link ActivityStartInterceptorTest}.
|
* Unit tests for {@link ActivityStartInterceptorTest}.
|
||||||
*
|
*
|
||||||
* Build/Install/Run:
|
* Build/Install/Run:
|
||||||
* atest WmTests:ActivityStartInterceptorTest
|
* atest WmTests:ActivityStartInterceptorTest
|
||||||
*/
|
*/
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@Presubmit
|
@Presubmit
|
||||||
@@ -114,6 +116,9 @@ public class ActivityStartInterceptorTest {
|
|||||||
private ActivityStartInterceptor mInterceptor;
|
private ActivityStartInterceptor mInterceptor;
|
||||||
private ActivityInfo mAInfo = new ActivityInfo();
|
private ActivityInfo mAInfo = new ActivityInfo();
|
||||||
|
|
||||||
|
private SparseArray<ActivityInterceptorCallback> mActivityInterceptorCallbacks =
|
||||||
|
new SparseArray<>();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
@@ -157,6 +162,9 @@ public class ActivityStartInterceptorTest {
|
|||||||
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
|
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
|
||||||
.thenReturn(true);
|
.thenReturn(true);
|
||||||
|
|
||||||
|
// Mock the activity start callbacks
|
||||||
|
when(mService.getActivityInterceptorCallbacks()).thenReturn(mActivityInterceptorCallbacks);
|
||||||
|
|
||||||
// Initialise activity info
|
// Initialise activity info
|
||||||
mAInfo.applicationInfo = new ApplicationInfo();
|
mAInfo.applicationInfo = new ApplicationInfo();
|
||||||
mAInfo.packageName = mAInfo.applicationInfo.packageName = TEST_PACKAGE_NAME;
|
mAInfo.packageName = mAInfo.applicationInfo.packageName = TEST_PACKAGE_NAME;
|
||||||
@@ -285,4 +293,38 @@ public class ActivityStartInterceptorTest {
|
|||||||
// THEN calling intercept returns false
|
// THEN calling intercept returns false
|
||||||
assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
|
assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addMockInterceptorCallback(@Nullable Intent intent) {
|
||||||
|
int size = mActivityInterceptorCallbacks.size();
|
||||||
|
mActivityInterceptorCallbacks.put(size, new ActivityInterceptorCallback() {
|
||||||
|
@Override
|
||||||
|
public Intent intercept(ActivityInterceptorInfo info) {
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterceptionCallback_singleCallback() {
|
||||||
|
addMockInterceptorCallback(new Intent("android.test.foo"));
|
||||||
|
|
||||||
|
assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
|
||||||
|
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterceptionCallback_singleCallbackReturnsNull() {
|
||||||
|
addMockInterceptorCallback(null);
|
||||||
|
|
||||||
|
assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterceptionCallback_fallbackToSecondCallback() {
|
||||||
|
addMockInterceptorCallback(null);
|
||||||
|
addMockInterceptorCallback(new Intent("android.test.second"));
|
||||||
|
|
||||||
|
assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
|
||||||
|
assertEquals("android.test.second", mInterceptor.mIntent.getAction());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
|||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
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.mockitoSession;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
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.ActivityRecord.State.PAUSED;
|
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.PAUSING;
|
||||||
import static com.android.server.wm.ActivityRecord.State.RESUMED;
|
import static com.android.server.wm.ActivityRecord.State.RESUMED;
|
||||||
@@ -42,12 +44,14 @@ import static org.mockito.Mockito.doCallRealMethod;
|
|||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.IApplicationThread;
|
import android.app.IApplicationThread;
|
||||||
import android.app.PictureInPictureParams;
|
import android.app.PictureInPictureParams;
|
||||||
import android.app.servertransaction.ClientTransaction;
|
import android.app.servertransaction.ClientTransaction;
|
||||||
import android.app.servertransaction.EnterPipRequestedItem;
|
import android.app.servertransaction.EnterPipRequestedItem;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
@@ -846,7 +850,64 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
|
|||||||
return wpc;
|
return wpc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testRegisterActivityStartInterceptor_IndexTooSmall() {
|
||||||
|
mAtm.mInternal.registerActivityStartInterceptor(FIRST_ORDERED_ID - 1,
|
||||||
|
new ActivityInterceptorCallback() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Intent intercept(ActivityInterceptorInfo info) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testRegisterActivityStartInterceptor_IndexTooLarge() {
|
||||||
|
mAtm.mInternal.registerActivityStartInterceptor(LAST_ORDERED_ID + 1,
|
||||||
|
new ActivityInterceptorCallback() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Intent intercept(ActivityInterceptorInfo info) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testRegisterActivityStartInterceptor_DuplicateId() {
|
||||||
|
mAtm.mInternal.registerActivityStartInterceptor(FIRST_ORDERED_ID,
|
||||||
|
new ActivityInterceptorCallback() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Intent intercept(ActivityInterceptorInfo info) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mAtm.mInternal.registerActivityStartInterceptor(FIRST_ORDERED_ID,
|
||||||
|
new ActivityInterceptorCallback() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Intent intercept(ActivityInterceptorInfo info) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterActivityStartInterceptor() {
|
||||||
|
assertEquals(0, mAtm.getActivityInterceptorCallbacks().size());
|
||||||
|
|
||||||
|
mAtm.mInternal.registerActivityStartInterceptor(FIRST_ORDERED_ID,
|
||||||
|
new ActivityInterceptorCallback() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Intent intercept(ActivityInterceptorInfo info) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(1, mAtm.getActivityInterceptorCallbacks().size());
|
||||||
|
assertTrue(mAtm.getActivityInterceptorCallbacks().contains(FIRST_ORDERED_ID));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user