Merge "Check visibility for consecutive launch while device is sleeping" into sc-v2-dev am: 6da7b677c8

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15435679

Change-Id: Ida14198ed1186cc0ce1ebb0b694dbbbeea6c5fbb
This commit is contained in:
Riddle Hsu
2021-08-04 02:06:42 +00:00
committed by Automerger Merge Worker
2 changed files with 46 additions and 14 deletions

View File

@@ -633,6 +633,7 @@ class ActivityMetricsLogger {
if (crossPackage) { if (crossPackage) {
startLaunchTrace(info); startLaunchTrace(info);
} }
scheduleCheckActivityToBeDrawnIfSleeping(launchedActivity);
return; return;
} }
@@ -654,13 +655,7 @@ class ActivityMetricsLogger {
// As abort for no process switch. // As abort for no process switch.
launchObserverNotifyIntentFailed(); launchObserverNotifyIntentFailed();
} }
if (launchedActivity.mDisplayContent.isSleeping()) { scheduleCheckActivityToBeDrawnIfSleeping(launchedActivity);
// It is unknown whether the activity can be drawn or not, e.g. it depends on the
// keyguard states and the attributes or flags set by the activity. If the activity
// keeps invisible in the grace period, the tracker will be cancelled so it won't get
// a very long launch time that takes unlocking as the end of launch.
scheduleCheckActivityToBeDrawn(launchedActivity, UNKNOWN_VISIBILITY_CHECK_DELAY_MS);
}
// If the previous transitions are no longer visible, abort them to avoid counting the // If the previous transitions are no longer visible, abort them to avoid counting the
// launch time when resuming from back stack. E.g. launch 2 independent tasks in a short // launch time when resuming from back stack. E.g. launch 2 independent tasks in a short
@@ -675,6 +670,16 @@ class ActivityMetricsLogger {
} }
} }
private void scheduleCheckActivityToBeDrawnIfSleeping(@NonNull ActivityRecord r) {
if (r.mDisplayContent.isSleeping()) {
// It is unknown whether the activity can be drawn or not, e.g. it depends on the
// keyguard states and the attributes or flags set by the activity. If the activity
// keeps invisible in the grace period, the tracker will be cancelled so it won't get
// a very long launch time that takes unlocking as the end of launch.
scheduleCheckActivityToBeDrawn(r, UNKNOWN_VISIBILITY_CHECK_DELAY_MS);
}
}
/** /**
* Notifies the tracker that all windows of the app have been drawn. * Notifies the tracker that all windows of the app have been drawn.
* *

View File

@@ -27,6 +27,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMor
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat;
@@ -70,6 +71,7 @@ import java.util.function.ToIntFunction;
@Presubmit @Presubmit
@RunWith(WindowTestRunner.class) @RunWith(WindowTestRunner.class)
public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
private static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5);
private ActivityMetricsLogger mActivityMetricsLogger; private ActivityMetricsLogger mActivityMetricsLogger;
private ActivityMetricsLogger.LaunchingState mLaunchingState; private ActivityMetricsLogger.LaunchingState mLaunchingState;
private ActivityMetricsLaunchObserver mLaunchObserver; private ActivityMetricsLaunchObserver mLaunchObserver;
@@ -137,7 +139,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
// messages that are waiting for the lock. // messages that are waiting for the lock.
waitHandlerIdle(mAtm.mH); waitHandlerIdle(mAtm.mH);
// AMLO callbacks happen on a separate thread than AML calls, so we need to use a timeout. // AMLO callbacks happen on a separate thread than AML calls, so we need to use a timeout.
return verify(mock, timeout(TimeUnit.SECONDS.toMillis(5))); return verify(mock, timeout(TIMEOUT_MS));
} }
private void verifyOnActivityLaunchFinished(ActivityRecord activity) { private void verifyOnActivityLaunchFinished(ActivityRecord activity) {
@@ -258,15 +260,40 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
@Test @Test
public void testOnActivityLaunchWhileSleeping() { public void testOnActivityLaunchWhileSleeping() {
notifyActivityLaunching(mTopActivity.intent); notifyActivityLaunching(mTrampolineActivity.intent);
notifyActivityLaunched(START_SUCCESS, mTopActivity); notifyActivityLaunched(START_SUCCESS, mTrampolineActivity);
doReturn(true).when(mTopActivity.mDisplayContent).isSleeping(); doReturn(true).when(mTrampolineActivity.mDisplayContent).isSleeping();
mTopActivity.setState(ActivityRecord.State.RESUMED, "test"); mTrampolineActivity.setState(ActivityRecord.State.RESUMED, "test");
mTopActivity.setVisibility(false); mTrampolineActivity.setVisibility(false);
waitHandlerIdle(mAtm.mH); waitHandlerIdle(mAtm.mH);
// Not cancel immediately because in one of real cases, the keyguard may be going away or // Not cancel immediately because in one of real cases, the keyguard may be going away or
// occluded later, then the activity can be drawn. // occluded later, then the activity can be drawn.
verify(mLaunchObserver, never()).onActivityLaunchCancelled(eqProto(mTopActivity)); verify(mLaunchObserver, never()).onActivityLaunchCancelled(eqProto(mTrampolineActivity));
clearInvocations(mLaunchObserver);
mLaunchTopByTrampoline = true;
mTopActivity.mVisibleRequested = false;
notifyActivityLaunching(mTopActivity.intent);
// It should schedule a message with UNKNOWN_VISIBILITY_CHECK_DELAY_MS to check whether
// the launch event is still valid.
notifyActivityLaunched(START_SUCCESS, mTopActivity);
// The posted message will acquire wm lock, so the test needs to release the lock to verify.
final Throwable error = awaitInWmLock(() -> {
try {
// Though the aborting target should be eqProto(mTopActivity), use any() to avoid
// any changes in proto that may cause failure by different arguments.
verify(mLaunchObserver, timeout(TIMEOUT_MS)).onActivityLaunchCancelled(any());
} catch (Throwable e) {
// Catch any errors including assertion because this runs in another thread.
return e;
}
return null;
});
// The launch event must be cancelled because the activity keeps invisible.
if (error != null) {
throw new AssertionError(error);
}
} }
@Test @Test