Merge "Log AppCompatStateChanged atom." into sc-v2-dev am: 504e61e8de
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15583144 Change-Id: Idfd43a8bce596053b37a87f6e74159918bde3958
This commit is contained in:
@@ -59,6 +59,8 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_T
|
|||||||
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
|
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
|
||||||
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
|
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
|
||||||
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
|
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
|
||||||
import static com.android.server.am.MemoryStatUtil.MemoryStat;
|
import static com.android.server.am.MemoryStatUtil.MemoryStat;
|
||||||
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
|
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
|
||||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
|
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
|
||||||
@@ -89,6 +91,7 @@ import android.util.ArrayMap;
|
|||||||
import android.util.EventLog;
|
import android.util.EventLog;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.util.TimeUtils;
|
import android.util.TimeUtils;
|
||||||
import android.util.proto.ProtoOutputStream;
|
import android.util.proto.ProtoOutputStream;
|
||||||
|
|
||||||
@@ -157,6 +160,9 @@ class ActivityMetricsLogger {
|
|||||||
private final ArrayList<TransitionInfo> mTransitionInfoList = new ArrayList<>();
|
private final ArrayList<TransitionInfo> mTransitionInfoList = new ArrayList<>();
|
||||||
/** Map : Last launched activity => {@link TransitionInfo} */
|
/** Map : Last launched activity => {@link TransitionInfo} */
|
||||||
private final ArrayMap<ActivityRecord, TransitionInfo> mLastTransitionInfo = new ArrayMap<>();
|
private final ArrayMap<ActivityRecord, TransitionInfo> mLastTransitionInfo = new ArrayMap<>();
|
||||||
|
/** SparseArray : Package UID => {@link PackageCompatStateInfo} */
|
||||||
|
private final SparseArray<PackageCompatStateInfo> mPackageUidToCompatStateInfo =
|
||||||
|
new SparseArray<>(0);
|
||||||
|
|
||||||
private ArtManagerInternal mArtManagerInternal;
|
private ArtManagerInternal mArtManagerInternal;
|
||||||
private final StringBuilder mStringBuilder = new StringBuilder();
|
private final StringBuilder mStringBuilder = new StringBuilder();
|
||||||
@@ -452,6 +458,15 @@ class ActivityMetricsLogger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Information about the App Compat state logging associated with a package UID . */
|
||||||
|
private static final class PackageCompatStateInfo {
|
||||||
|
/** All activities that have a visible state. */
|
||||||
|
final ArrayList<ActivityRecord> mVisibleActivities = new ArrayList<>();
|
||||||
|
/** The last logged state. */
|
||||||
|
int mLastLoggedState = APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
|
||||||
|
@Nullable ActivityRecord mLastLoggedActivity;
|
||||||
|
}
|
||||||
|
|
||||||
ActivityMetricsLogger(ActivityTaskSupervisor supervisor, Looper looper) {
|
ActivityMetricsLogger(ActivityTaskSupervisor supervisor, Looper looper) {
|
||||||
mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
|
mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
|
||||||
mSupervisor = supervisor;
|
mSupervisor = supervisor;
|
||||||
@@ -775,6 +790,21 @@ class ActivityMetricsLogger {
|
|||||||
/** Makes sure that the reference to the removed activity is cleared. */
|
/** Makes sure that the reference to the removed activity is cleared. */
|
||||||
void notifyActivityRemoved(@NonNull ActivityRecord r) {
|
void notifyActivityRemoved(@NonNull ActivityRecord r) {
|
||||||
mLastTransitionInfo.remove(r);
|
mLastTransitionInfo.remove(r);
|
||||||
|
|
||||||
|
final int packageUid = r.info.applicationInfo.uid;
|
||||||
|
final PackageCompatStateInfo compatStateInfo = mPackageUidToCompatStateInfo.get(packageUid);
|
||||||
|
if (compatStateInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
compatStateInfo.mVisibleActivities.remove(r);
|
||||||
|
if (compatStateInfo.mLastLoggedActivity == r) {
|
||||||
|
compatStateInfo.mLastLoggedActivity = null;
|
||||||
|
}
|
||||||
|
if (compatStateInfo.mVisibleActivities.isEmpty()) {
|
||||||
|
// No need to keep the entry if there are no visible activities.
|
||||||
|
mPackageUidToCompatStateInfo.remove(packageUid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1271,6 +1301,115 @@ class ActivityMetricsLogger {
|
|||||||
memoryStat.swapInBytes);
|
memoryStat.swapInBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the current App Compat state of the given {@link ActivityRecord} with its package
|
||||||
|
* UID, if all of the following hold:
|
||||||
|
* <ul>
|
||||||
|
* <li>The current state is different than the last logged state for the package UID of the
|
||||||
|
* activity.
|
||||||
|
* <li>If the current state is NOT_VISIBLE, there is a previously logged state for the
|
||||||
|
* package UID and there are no other visible activities with the same package UID.
|
||||||
|
* <li>The last logged activity with the same package UID is either {@code activity} or the
|
||||||
|
* last logged state is NOT_VISIBLE or NOT_LETTERBOXED.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>If the current state is NOT_VISIBLE and the previous state which was logged by {@code
|
||||||
|
* activity} wasn't, looks for the first visible activity with the same package UID that has
|
||||||
|
* a letterboxed state, or a non-letterboxed state if there isn't one, and logs that state.
|
||||||
|
*
|
||||||
|
* <p>This method assumes that the caller is wrapping the call with a synchronized block so
|
||||||
|
* that there won't be a race condition between two activities with the same package.
|
||||||
|
*/
|
||||||
|
void logAppCompatState(@NonNull ActivityRecord activity) {
|
||||||
|
final int packageUid = activity.info.applicationInfo.uid;
|
||||||
|
final int state = activity.getAppCompatState();
|
||||||
|
|
||||||
|
if (!mPackageUidToCompatStateInfo.contains(packageUid)) {
|
||||||
|
mPackageUidToCompatStateInfo.put(packageUid, new PackageCompatStateInfo());
|
||||||
|
}
|
||||||
|
final PackageCompatStateInfo compatStateInfo = mPackageUidToCompatStateInfo.get(packageUid);
|
||||||
|
final int lastLoggedState = compatStateInfo.mLastLoggedState;
|
||||||
|
final ActivityRecord lastLoggedActivity = compatStateInfo.mLastLoggedActivity;
|
||||||
|
|
||||||
|
final boolean isVisible = state != APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
|
||||||
|
final ArrayList<ActivityRecord> visibleActivities = compatStateInfo.mVisibleActivities;
|
||||||
|
if (isVisible && !visibleActivities.contains(activity)) {
|
||||||
|
visibleActivities.add(activity);
|
||||||
|
} else if (!isVisible) {
|
||||||
|
visibleActivities.remove(activity);
|
||||||
|
if (visibleActivities.isEmpty()) {
|
||||||
|
// No need to keep the entry if there are no visible activities.
|
||||||
|
mPackageUidToCompatStateInfo.remove(packageUid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == lastLoggedState) {
|
||||||
|
// We don’t want to log the same state twice or log DEFAULT_NOT_VISIBLE before any
|
||||||
|
// visible state was logged.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isVisible && !visibleActivities.isEmpty()) {
|
||||||
|
// There is another visible activity for this package UID.
|
||||||
|
if (activity == lastLoggedActivity) {
|
||||||
|
// Make sure a new visible state is logged if needed.
|
||||||
|
findAppCompatStateToLog(compatStateInfo, packageUid);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activity != lastLoggedActivity
|
||||||
|
&& lastLoggedState != APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE
|
||||||
|
&& lastLoggedState != APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED) {
|
||||||
|
// Another visible activity for this package UID has logged a letterboxed state.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logAppCompatStateInternal(activity, state, packageUid, compatStateInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for the first visible activity in {@code compatStateInfo} that has a letterboxed
|
||||||
|
* state, or a non-letterboxed state if there isn't one, and logs that state for the given
|
||||||
|
* {@code packageUid}.
|
||||||
|
*/
|
||||||
|
private void findAppCompatStateToLog(PackageCompatStateInfo compatStateInfo, int packageUid) {
|
||||||
|
final ArrayList<ActivityRecord> visibleActivities = compatStateInfo.mVisibleActivities;
|
||||||
|
|
||||||
|
ActivityRecord activityToLog = null;
|
||||||
|
int stateToLog = APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
|
||||||
|
for (int i = 0; i < visibleActivities.size(); i++) {
|
||||||
|
ActivityRecord activity = visibleActivities.get(i);
|
||||||
|
int state = activity.getAppCompatState();
|
||||||
|
if (state == APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE) {
|
||||||
|
// This shouldn't happen.
|
||||||
|
Slog.w(TAG, "Visible activity with NOT_VISIBLE App Compat state for package UID: "
|
||||||
|
+ packageUid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (stateToLog == APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE || (
|
||||||
|
stateToLog == APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED
|
||||||
|
&& state != APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED)) {
|
||||||
|
activityToLog = activity;
|
||||||
|
stateToLog = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (activityToLog != null && stateToLog != APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE) {
|
||||||
|
logAppCompatStateInternal(activityToLog, stateToLog, packageUid, compatStateInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logAppCompatStateInternal(@NonNull ActivityRecord activity, int state,
|
||||||
|
int packageUid, PackageCompatStateInfo compatStateInfo) {
|
||||||
|
compatStateInfo.mLastLoggedState = state;
|
||||||
|
compatStateInfo.mLastLoggedActivity = activity;
|
||||||
|
FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPAT_STATE_CHANGED, packageUid, state);
|
||||||
|
|
||||||
|
if (DEBUG_METRICS) {
|
||||||
|
Slog.i(TAG, String.format("APP_COMPAT_STATE_CHANGED(%s, %s)", packageUid, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ArtManagerInternal getArtManagerInternal() {
|
private ArtManagerInternal getArtManagerInternal() {
|
||||||
if (mArtManagerInternal == null) {
|
if (mArtManagerInternal == null) {
|
||||||
// Note that this may be null.
|
// Note that this may be null.
|
||||||
|
|||||||
@@ -127,6 +127,11 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
|
|||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SWITCH;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SWITCH;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_FIXED_ORIENTATION;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
|
||||||
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
|
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
|
||||||
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
|
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
|
||||||
import static com.android.server.wm.ActivityRecord.State.DESTROYED;
|
import static com.android.server.wm.ActivityRecord.State.DESTROYED;
|
||||||
@@ -4692,6 +4697,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
|
ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
|
||||||
mTaskSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
|
mTaskSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
|
||||||
mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
|
mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
|
||||||
|
logAppCompatState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -7438,6 +7444,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
}
|
}
|
||||||
resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
|
resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logAppCompatState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -7447,18 +7455,55 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
* LetterboxUiController#shouldShowLetterboxUi} for more context.
|
* LetterboxUiController#shouldShowLetterboxUi} for more context.
|
||||||
*/
|
*/
|
||||||
boolean areBoundsLetterboxed() {
|
boolean areBoundsLetterboxed() {
|
||||||
|
return getAppCompatState(/* ignoreVisibility= */ true)
|
||||||
|
!= APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the current App Compat state via {@link ActivityMetricsLogger#logAppCompatState}.
|
||||||
|
*/
|
||||||
|
private void logAppCompatState() {
|
||||||
|
mTaskSupervisor.getActivityMetricsLogger().logAppCompatState(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current App Compat state of this activity.
|
||||||
|
*
|
||||||
|
* <p>The App Compat state indicates whether the activity is visible and letterboxed, and if so
|
||||||
|
* what is the reason for letterboxing. The state is used for logging the time spent in
|
||||||
|
* letterbox (sliced by the reason) vs non-letterbox per app.
|
||||||
|
*/
|
||||||
|
int getAppCompatState() {
|
||||||
|
return getAppCompatState(/* ignoreVisibility= */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #getAppCompatState()} except when {@code ignoreVisibility} the visibility
|
||||||
|
* of the activity is ignored.
|
||||||
|
*
|
||||||
|
* @param ignoreVisibility whether to ignore the visibility of the activity and not return
|
||||||
|
* NOT_VISIBLE if {@code mVisibleRequested} is false.
|
||||||
|
*/
|
||||||
|
private int getAppCompatState(boolean ignoreVisibility) {
|
||||||
|
if (!ignoreVisibility && !mVisibleRequested) {
|
||||||
|
return APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
|
||||||
|
}
|
||||||
if (mInSizeCompatModeForBounds) {
|
if (mInSizeCompatModeForBounds) {
|
||||||
return true;
|
return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE;
|
||||||
}
|
}
|
||||||
// Letterbox for fixed orientation. This check returns true only when an activity is
|
// Letterbox for fixed orientation. This check returns true only when an activity is
|
||||||
// letterboxed for fixed orientation. Aspect ratio restrictions are also applied if
|
// letterboxed for fixed orientation. Aspect ratio restrictions are also applied if
|
||||||
// present. But this doesn't return true when the activity is letterboxed only because
|
// present. But this doesn't return true when the activity is letterboxed only because
|
||||||
// of aspect ratio restrictions.
|
// of aspect ratio restrictions.
|
||||||
if (isLetterboxedForFixedOrientationAndAspectRatio()) {
|
if (isLetterboxedForFixedOrientationAndAspectRatio()) {
|
||||||
return true;
|
return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_FIXED_ORIENTATION;
|
||||||
}
|
}
|
||||||
// Letterbox for limited aspect ratio.
|
// Letterbox for limited aspect ratio.
|
||||||
return mIsAspectRatioApplied;
|
if (mIsAspectRatioApplied) {
|
||||||
|
return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
|||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_FIXED_ORIENTATION;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED;
|
||||||
|
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
|
||||||
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
|
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
|
||||||
import static com.android.server.wm.ActivityRecord.State.RESUMED;
|
import static com.android.server.wm.ActivityRecord.State.RESUMED;
|
||||||
import static com.android.server.wm.ActivityRecord.State.STOPPED;
|
import static com.android.server.wm.ActivityRecord.State.STOPPED;
|
||||||
@@ -55,7 +60,9 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.ArgumentMatchers.same;
|
import static org.mockito.ArgumentMatchers.same;
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.clearInvocations;
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
import static org.mockito.Mockito.doCallRealMethod;
|
import static org.mockito.Mockito.doCallRealMethod;
|
||||||
|
|
||||||
@@ -101,10 +108,14 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
|
|
||||||
private Task mTask;
|
private Task mTask;
|
||||||
private ActivityRecord mActivity;
|
private ActivityRecord mActivity;
|
||||||
|
private ActivityMetricsLogger mActivityMetricsLogger;
|
||||||
private Properties mInitialConstrainDisplayApisFlags;
|
private Properties mInitialConstrainDisplayApisFlags;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
mActivityMetricsLogger = mock(ActivityMetricsLogger.class);
|
||||||
|
clearInvocations(mActivityMetricsLogger);
|
||||||
|
doReturn(mActivityMetricsLogger).when(mAtm.mTaskSupervisor).getActivityMetricsLogger();
|
||||||
mInitialConstrainDisplayApisFlags = DeviceConfig.getProperties(
|
mInitialConstrainDisplayApisFlags = DeviceConfig.getProperties(
|
||||||
NAMESPACE_CONSTRAIN_DISPLAY_APIS);
|
NAMESPACE_CONSTRAIN_DISPLAY_APIS);
|
||||||
DeviceConfig.setProperties(
|
DeviceConfig.setProperties(
|
||||||
@@ -1939,13 +1950,19 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
setUpDisplaySizeWithApp(1000, 2500);
|
setUpDisplaySizeWithApp(1000, 2500);
|
||||||
|
|
||||||
assertFalse(mActivity.areBoundsLetterboxed());
|
assertFalse(mActivity.areBoundsLetterboxed());
|
||||||
|
verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED);
|
||||||
|
|
||||||
prepareUnresizable(mActivity, /* maxAspect= */ 2, SCREEN_ORIENTATION_PORTRAIT);
|
prepareUnresizable(mActivity, /* maxAspect= */ 2, SCREEN_ORIENTATION_PORTRAIT);
|
||||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||||
assertFalse(mActivity.inSizeCompatMode());
|
assertFalse(mActivity.inSizeCompatMode());
|
||||||
assertTrue(mActivity.areBoundsLetterboxed());
|
assertTrue(mActivity.areBoundsLetterboxed());
|
||||||
|
|
||||||
|
verifyLogAppCompatState(mActivity,
|
||||||
|
APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO);
|
||||||
|
|
||||||
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
|
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
|
||||||
|
verifyLogAppCompatState(mActivity,
|
||||||
|
APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE);
|
||||||
rotateDisplay(mActivity.mDisplayContent, ROTATION_0);
|
rotateDisplay(mActivity.mDisplayContent, ROTATION_0);
|
||||||
|
|
||||||
// After returning to the original rotation, bounds are computed in
|
// After returning to the original rotation, bounds are computed in
|
||||||
@@ -1955,6 +1972,18 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||||
assertFalse(mActivity.inSizeCompatMode());
|
assertFalse(mActivity.inSizeCompatMode());
|
||||||
assertTrue(mActivity.areBoundsLetterboxed());
|
assertTrue(mActivity.areBoundsLetterboxed());
|
||||||
|
verifyLogAppCompatState(mActivity,
|
||||||
|
APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO);
|
||||||
|
|
||||||
|
// After setting the visibility of the activity to false, areBoundsLetterboxed() still
|
||||||
|
// returns true but the NOT_VISIBLE App Compat state is logged.
|
||||||
|
mActivity.setVisibility(false);
|
||||||
|
assertTrue(mActivity.areBoundsLetterboxed());
|
||||||
|
verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE);
|
||||||
|
mActivity.setVisibility(true);
|
||||||
|
assertTrue(mActivity.areBoundsLetterboxed());
|
||||||
|
verifyLogAppCompatState(mActivity,
|
||||||
|
APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1963,12 +1992,15 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
|
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
|
||||||
|
|
||||||
assertFalse(mActivity.areBoundsLetterboxed());
|
assertFalse(mActivity.areBoundsLetterboxed());
|
||||||
|
verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED);
|
||||||
|
|
||||||
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
|
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
|
||||||
|
|
||||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||||
assertFalse(mActivity.inSizeCompatMode());
|
assertFalse(mActivity.inSizeCompatMode());
|
||||||
assertTrue(mActivity.areBoundsLetterboxed());
|
assertTrue(mActivity.areBoundsLetterboxed());
|
||||||
|
verifyLogAppCompatState(mActivity,
|
||||||
|
APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_FIXED_ORIENTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1978,12 +2010,15 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
|
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
|
||||||
|
|
||||||
assertFalse(mActivity.areBoundsLetterboxed());
|
assertFalse(mActivity.areBoundsLetterboxed());
|
||||||
|
verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED);
|
||||||
|
|
||||||
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
|
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
|
||||||
|
|
||||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||||
assertTrue(mActivity.inSizeCompatMode());
|
assertTrue(mActivity.inSizeCompatMode());
|
||||||
assertTrue(mActivity.areBoundsLetterboxed());
|
assertTrue(mActivity.areBoundsLetterboxed());
|
||||||
|
verifyLogAppCompatState(mActivity,
|
||||||
|
APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2197,6 +2232,11 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
.isEqualTo(activity.getWindowConfiguration().getBounds());
|
.isEqualTo(activity.getWindowConfiguration().getBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void verifyLogAppCompatState(ActivityRecord activity, int state) {
|
||||||
|
verify(mActivityMetricsLogger, atLeastOnce()).logAppCompatState(
|
||||||
|
argThat(r -> activity == r && r.getAppCompatState() == state));
|
||||||
|
}
|
||||||
|
|
||||||
static Configuration rotateDisplay(DisplayContent display, int rotation) {
|
static Configuration rotateDisplay(DisplayContent display, int rotation) {
|
||||||
final Configuration c = new Configuration();
|
final Configuration c = new Configuration();
|
||||||
display.getDisplayRotation().setRotation(rotation);
|
display.getDisplayRotation().setRotation(rotation);
|
||||||
|
|||||||
Reference in New Issue
Block a user