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:
@@ -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.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user