Loading core/java/com/android/internal/jank/DisplayResolutionTracker.java 0 → 100644 +162 −0 Original line number Diff line number Diff line /* * 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.internal.jank; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__FHD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__HD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__QHD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__SD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__UNKNOWN_RESOLUTION; import android.annotation.IntDef; import android.annotation.Nullable; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.os.Handler; import android.util.SparseArray; import android.view.DisplayInfo; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * A class that tracks the display resolutions. * @hide */ public class DisplayResolutionTracker { private static final String TAG = DisplayResolutionTracker.class.getSimpleName(); public static final int RESOLUTION_UNKNOWN = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__UNKNOWN_RESOLUTION; public static final int RESOLUTION_SD = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__SD; public static final int RESOLUTION_HD = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__HD; public static final int RESOLUTION_FHD = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__FHD; public static final int RESOLUTION_QHD = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__QHD; /** @hide */ @IntDef({ RESOLUTION_UNKNOWN, RESOLUTION_SD, RESOLUTION_HD, RESOLUTION_FHD, RESOLUTION_QHD, }) @Retention(RetentionPolicy.SOURCE) public @interface Resolution { } private final DisplayInterface mManager; private final SparseArray<Integer> mResolutions = new SparseArray<>(); private final Object mLock = new Object(); public DisplayResolutionTracker(@Nullable Handler handler) { this(DisplayInterface.getDefault(handler)); } @VisibleForTesting public DisplayResolutionTracker(DisplayInterface manager) { mManager = manager; mManager.registerDisplayListener(new DisplayManager.DisplayListener() { @Override public void onDisplayAdded(int displayId) { updateDisplay(displayId); } @Override public void onDisplayChanged(int displayId) { updateDisplay(displayId); } @Override public void onDisplayRemoved(int displayId) { // Not in the event mask below, won't be called. } }); } private void updateDisplay(int displayId) { DisplayInfo info = mManager.getDisplayInfo(displayId); @Resolution int resolution = getResolution(info); synchronized (mLock) { mResolutions.put(displayId, resolution); } } /** * Returns the (cached) resolution of the display with the given ID. */ @Resolution public int getResolution(int displayId) { return mResolutions.get(displayId, RESOLUTION_UNKNOWN); } /** * Returns the resolution of the given {@link DisplayInfo}. */ @VisibleForTesting @Resolution public static int getResolution(DisplayInfo info) { int smaller = Math.min(info.logicalWidth, info.logicalHeight); int larger = Math.max(info.logicalWidth, info.logicalHeight); if (smaller < 720 || larger < 1280) { return RESOLUTION_SD; } else if (smaller < 1080 || larger < 1920) { return RESOLUTION_HD; } else if (smaller < 1440 || larger < 2560) { return RESOLUTION_FHD; } else { return RESOLUTION_QHD; } } /** * Wrapper around the final {@link DisplayManagerGlobal} class. * @hide */ @VisibleForTesting public interface DisplayInterface { /** Reurns an implementation wrapping {@link DisplayManagerGlobal}. */ static DisplayInterface getDefault(@Nullable Handler handler) { DisplayManagerGlobal manager = DisplayManagerGlobal.getInstance(); return new DisplayInterface() { @Override public void registerDisplayListener(DisplayManager.DisplayListener listener) { manager.registerDisplayListener(listener, handler, DisplayManager.EVENT_FLAG_DISPLAY_ADDED | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED); } @Override public DisplayInfo getDisplayInfo(int displayId) { return manager.getDisplayInfo(displayId); } }; } /** {@see DisplayManagerGlobal#registerDisplayListener} */ void registerDisplayListener(DisplayManager.DisplayListener listener); /** {@see DisplayManagerGlobal#getDisplayInfo} */ DisplayInfo getDisplayInfo(int displayId); } } core/java/com/android/internal/jank/FrameTracker.java +13 −2 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener private final Session mSession; private final ViewRootWrapper mViewRoot; private final SurfaceControlWrapper mSurfaceControlWrapper; private final int mDisplayId; private final ViewRootImpl.SurfaceChangedCallback mSurfaceChangedCallback; private final Handler mHandler; private final ChoreographerWrapper mChoreographer; Loading Loading @@ -213,6 +214,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener mTraceThresholdMissedFrames = traceThresholdMissedFrames; mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis; mListener = listener; mDisplayId = config.getDisplayId(); if (mSurfaceOnly) { mSurfaceControl = config.getSurfaceControl(); Loading Loading @@ -625,6 +627,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener if (mSession.logToStatsd()) { mStatsLog.write( FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED, mDisplayId, mSession.getStatsdInteractionType(), totalFramesCount, missedFramesCount, Loading Loading @@ -785,9 +788,17 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } public static class StatsLogWrapper { public void write(int code, private final DisplayResolutionTracker mDisplayResolutionTracker; public StatsLogWrapper(DisplayResolutionTracker displayResolutionTracker) { mDisplayResolutionTracker = displayResolutionTracker; } /** {@see FrameworkStatsLog#write) */ public void write(int code, int displayId, int arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7) { FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7); FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, mDisplayResolutionTracker.getResolution(displayId)); } } Loading core/java/com/android/internal/jank/InteractionJankMonitor.java +12 −1 Original line number Diff line number Diff line Loading @@ -306,6 +306,7 @@ public class InteractionJankMonitor { @GuardedBy("mLock") private final SparseArray<Runnable> mTimeoutActions; private final HandlerThread mWorker; private final DisplayResolutionTracker mDisplayResolutionTracker; private final Object mLock = new Object(); private volatile boolean mEnabled = DEFAULT_ENABLED; Loading Loading @@ -408,6 +409,7 @@ public class InteractionJankMonitor { mWorker = worker; mWorker.start(); mSamplingInterval = DEFAULT_SAMPLING_INTERVAL; mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler()); // Post initialization to the background in case we're running on the main // thread. Loading Loading @@ -443,7 +445,8 @@ public class InteractionJankMonitor { final FrameMetricsWrapper frameMetrics = new FrameMetricsWrapper(); return new FrameTracker(this, session, config.getHandler(), threadedRenderer, viewRoot, surfaceControl, choreographer, frameMetrics, new FrameTracker.StatsLogWrapper(), surfaceControl, choreographer, frameMetrics, new FrameTracker.StatsLogWrapper(mDisplayResolutionTracker), mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis, eventsListener, config); } Loading Loading @@ -1098,6 +1101,14 @@ public class InteractionJankMonitor { public Handler getHandler() { return mHandler; } /** * @return the ID of the display this interaction in on. */ @VisibleForTesting public int getDisplayId() { return (mSurfaceOnly ? mContext.getDisplay() : mView.getDisplay()).getDisplayId(); } } /** Loading core/tests/coretests/src/com/android/internal/jank/DisplayResolutionTrackerTest.java 0 → 100644 +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.internal.jank; import static com.android.internal.jank.DisplayResolutionTracker.getResolution; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.display.DisplayManager; import android.view.DisplayInfo; import androidx.test.filters.SmallTest; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @SmallTest public class DisplayResolutionTrackerTest { private static final DisplayInfo SD = makeDisplayInfo(800, 600); private static final DisplayInfo HD = makeDisplayInfo(720, 1280); private static final DisplayInfo FHD = makeDisplayInfo(2340, 1080); private static final DisplayInfo QHD = makeDisplayInfo(3120, 1440); private DisplayResolutionTracker.DisplayInterface mDisplayManager; private ArgumentCaptor<DisplayManager.DisplayListener> mListenerCaptor; private DisplayResolutionTracker mTracker; @Before public void setup() throws Exception { mDisplayManager = mock(DisplayResolutionTracker.DisplayInterface.class); mListenerCaptor = ArgumentCaptor.forClass(DisplayManager.DisplayListener.class); mTracker = new DisplayResolutionTracker(mDisplayManager); verify(mDisplayManager).registerDisplayListener(mListenerCaptor.capture()); } @Test public void testResolutionMapping() { assertThat(getResolution(SD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_SD); assertThat(getResolution(HD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_HD); assertThat(getResolution(FHD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_FHD); assertThat(getResolution(QHD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_QHD); } @Test public void testResolutionUpdatesOnDisplayChanges() throws Exception { assertThat(mTracker.getResolution(42)) .isEqualTo(DisplayResolutionTracker.RESOLUTION_UNKNOWN); when(mDisplayManager.getDisplayInfo(42)).thenReturn(FHD, QHD); mListenerCaptor.getValue().onDisplayAdded(42); assertThat(mTracker.getResolution(42)) .isEqualTo(DisplayResolutionTracker.RESOLUTION_FHD); mListenerCaptor.getValue().onDisplayChanged(42); assertThat(mTracker.getResolution(42)) .isEqualTo(DisplayResolutionTracker.RESOLUTION_QHD); } private static DisplayInfo makeDisplayInfo(int width, int height) { DisplayInfo info = new DisplayInfo(); info.logicalWidth = width; info.logicalHeight = height; return info; } } core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java +11 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,7 @@ public class FrameTrackerTest { when(config.isSurfaceOnly()).thenReturn(surfaceOnly); when(config.getSurfaceControl()).thenReturn(mSurfaceControl); when(config.shouldDeferMonitor()).thenReturn(true); when(config.getDisplayId()).thenReturn(42); View view = mRule.getActivity().getWindow().getDecorView(); Handler spyHandler = spy(new Handler(handler.getLooper())); when(config.getView()).thenReturn(surfaceOnly ? null : view); Loading Loading @@ -168,6 +169,7 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -204,6 +206,7 @@ public class FrameTrackerTest { verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, Loading Loading @@ -240,6 +243,7 @@ public class FrameTrackerTest { verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -276,6 +280,7 @@ public class FrameTrackerTest { verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, Loading Loading @@ -315,6 +320,7 @@ public class FrameTrackerTest { verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, Loading Loading @@ -356,6 +362,7 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -483,6 +490,7 @@ public class FrameTrackerTest { verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, Loading Loading @@ -519,6 +527,7 @@ public class FrameTrackerTest { verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -555,6 +564,7 @@ public class FrameTrackerTest { verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -585,6 +595,7 @@ public class FrameTrackerTest { verify(mSurfaceControlWrapper).removeJankStatsListener(any()); verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(6L) /* totalFrames */, eq(5L) /* missedFrames */, Loading Loading
core/java/com/android/internal/jank/DisplayResolutionTracker.java 0 → 100644 +162 −0 Original line number Diff line number Diff line /* * 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.internal.jank; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__FHD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__HD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__QHD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__SD; import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__UNKNOWN_RESOLUTION; import android.annotation.IntDef; import android.annotation.Nullable; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.os.Handler; import android.util.SparseArray; import android.view.DisplayInfo; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * A class that tracks the display resolutions. * @hide */ public class DisplayResolutionTracker { private static final String TAG = DisplayResolutionTracker.class.getSimpleName(); public static final int RESOLUTION_UNKNOWN = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__UNKNOWN_RESOLUTION; public static final int RESOLUTION_SD = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__SD; public static final int RESOLUTION_HD = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__HD; public static final int RESOLUTION_FHD = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__FHD; public static final int RESOLUTION_QHD = UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_RESOLUTION__QHD; /** @hide */ @IntDef({ RESOLUTION_UNKNOWN, RESOLUTION_SD, RESOLUTION_HD, RESOLUTION_FHD, RESOLUTION_QHD, }) @Retention(RetentionPolicy.SOURCE) public @interface Resolution { } private final DisplayInterface mManager; private final SparseArray<Integer> mResolutions = new SparseArray<>(); private final Object mLock = new Object(); public DisplayResolutionTracker(@Nullable Handler handler) { this(DisplayInterface.getDefault(handler)); } @VisibleForTesting public DisplayResolutionTracker(DisplayInterface manager) { mManager = manager; mManager.registerDisplayListener(new DisplayManager.DisplayListener() { @Override public void onDisplayAdded(int displayId) { updateDisplay(displayId); } @Override public void onDisplayChanged(int displayId) { updateDisplay(displayId); } @Override public void onDisplayRemoved(int displayId) { // Not in the event mask below, won't be called. } }); } private void updateDisplay(int displayId) { DisplayInfo info = mManager.getDisplayInfo(displayId); @Resolution int resolution = getResolution(info); synchronized (mLock) { mResolutions.put(displayId, resolution); } } /** * Returns the (cached) resolution of the display with the given ID. */ @Resolution public int getResolution(int displayId) { return mResolutions.get(displayId, RESOLUTION_UNKNOWN); } /** * Returns the resolution of the given {@link DisplayInfo}. */ @VisibleForTesting @Resolution public static int getResolution(DisplayInfo info) { int smaller = Math.min(info.logicalWidth, info.logicalHeight); int larger = Math.max(info.logicalWidth, info.logicalHeight); if (smaller < 720 || larger < 1280) { return RESOLUTION_SD; } else if (smaller < 1080 || larger < 1920) { return RESOLUTION_HD; } else if (smaller < 1440 || larger < 2560) { return RESOLUTION_FHD; } else { return RESOLUTION_QHD; } } /** * Wrapper around the final {@link DisplayManagerGlobal} class. * @hide */ @VisibleForTesting public interface DisplayInterface { /** Reurns an implementation wrapping {@link DisplayManagerGlobal}. */ static DisplayInterface getDefault(@Nullable Handler handler) { DisplayManagerGlobal manager = DisplayManagerGlobal.getInstance(); return new DisplayInterface() { @Override public void registerDisplayListener(DisplayManager.DisplayListener listener) { manager.registerDisplayListener(listener, handler, DisplayManager.EVENT_FLAG_DISPLAY_ADDED | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED); } @Override public DisplayInfo getDisplayInfo(int displayId) { return manager.getDisplayInfo(displayId); } }; } /** {@see DisplayManagerGlobal#registerDisplayListener} */ void registerDisplayListener(DisplayManager.DisplayListener listener); /** {@see DisplayManagerGlobal#getDisplayInfo} */ DisplayInfo getDisplayInfo(int displayId); } }
core/java/com/android/internal/jank/FrameTracker.java +13 −2 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener private final Session mSession; private final ViewRootWrapper mViewRoot; private final SurfaceControlWrapper mSurfaceControlWrapper; private final int mDisplayId; private final ViewRootImpl.SurfaceChangedCallback mSurfaceChangedCallback; private final Handler mHandler; private final ChoreographerWrapper mChoreographer; Loading Loading @@ -213,6 +214,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener mTraceThresholdMissedFrames = traceThresholdMissedFrames; mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis; mListener = listener; mDisplayId = config.getDisplayId(); if (mSurfaceOnly) { mSurfaceControl = config.getSurfaceControl(); Loading Loading @@ -625,6 +627,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener if (mSession.logToStatsd()) { mStatsLog.write( FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED, mDisplayId, mSession.getStatsdInteractionType(), totalFramesCount, missedFramesCount, Loading Loading @@ -785,9 +788,17 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener } public static class StatsLogWrapper { public void write(int code, private final DisplayResolutionTracker mDisplayResolutionTracker; public StatsLogWrapper(DisplayResolutionTracker displayResolutionTracker) { mDisplayResolutionTracker = displayResolutionTracker; } /** {@see FrameworkStatsLog#write) */ public void write(int code, int displayId, int arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7) { FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7); FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7, mDisplayResolutionTracker.getResolution(displayId)); } } Loading
core/java/com/android/internal/jank/InteractionJankMonitor.java +12 −1 Original line number Diff line number Diff line Loading @@ -306,6 +306,7 @@ public class InteractionJankMonitor { @GuardedBy("mLock") private final SparseArray<Runnable> mTimeoutActions; private final HandlerThread mWorker; private final DisplayResolutionTracker mDisplayResolutionTracker; private final Object mLock = new Object(); private volatile boolean mEnabled = DEFAULT_ENABLED; Loading Loading @@ -408,6 +409,7 @@ public class InteractionJankMonitor { mWorker = worker; mWorker.start(); mSamplingInterval = DEFAULT_SAMPLING_INTERVAL; mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler()); // Post initialization to the background in case we're running on the main // thread. Loading Loading @@ -443,7 +445,8 @@ public class InteractionJankMonitor { final FrameMetricsWrapper frameMetrics = new FrameMetricsWrapper(); return new FrameTracker(this, session, config.getHandler(), threadedRenderer, viewRoot, surfaceControl, choreographer, frameMetrics, new FrameTracker.StatsLogWrapper(), surfaceControl, choreographer, frameMetrics, new FrameTracker.StatsLogWrapper(mDisplayResolutionTracker), mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis, eventsListener, config); } Loading Loading @@ -1098,6 +1101,14 @@ public class InteractionJankMonitor { public Handler getHandler() { return mHandler; } /** * @return the ID of the display this interaction in on. */ @VisibleForTesting public int getDisplayId() { return (mSurfaceOnly ? mContext.getDisplay() : mView.getDisplay()).getDisplayId(); } } /** Loading
core/tests/coretests/src/com/android/internal/jank/DisplayResolutionTrackerTest.java 0 → 100644 +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.internal.jank; import static com.android.internal.jank.DisplayResolutionTracker.getResolution; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.display.DisplayManager; import android.view.DisplayInfo; import androidx.test.filters.SmallTest; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @SmallTest public class DisplayResolutionTrackerTest { private static final DisplayInfo SD = makeDisplayInfo(800, 600); private static final DisplayInfo HD = makeDisplayInfo(720, 1280); private static final DisplayInfo FHD = makeDisplayInfo(2340, 1080); private static final DisplayInfo QHD = makeDisplayInfo(3120, 1440); private DisplayResolutionTracker.DisplayInterface mDisplayManager; private ArgumentCaptor<DisplayManager.DisplayListener> mListenerCaptor; private DisplayResolutionTracker mTracker; @Before public void setup() throws Exception { mDisplayManager = mock(DisplayResolutionTracker.DisplayInterface.class); mListenerCaptor = ArgumentCaptor.forClass(DisplayManager.DisplayListener.class); mTracker = new DisplayResolutionTracker(mDisplayManager); verify(mDisplayManager).registerDisplayListener(mListenerCaptor.capture()); } @Test public void testResolutionMapping() { assertThat(getResolution(SD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_SD); assertThat(getResolution(HD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_HD); assertThat(getResolution(FHD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_FHD); assertThat(getResolution(QHD)).isEqualTo(DisplayResolutionTracker.RESOLUTION_QHD); } @Test public void testResolutionUpdatesOnDisplayChanges() throws Exception { assertThat(mTracker.getResolution(42)) .isEqualTo(DisplayResolutionTracker.RESOLUTION_UNKNOWN); when(mDisplayManager.getDisplayInfo(42)).thenReturn(FHD, QHD); mListenerCaptor.getValue().onDisplayAdded(42); assertThat(mTracker.getResolution(42)) .isEqualTo(DisplayResolutionTracker.RESOLUTION_FHD); mListenerCaptor.getValue().onDisplayChanged(42); assertThat(mTracker.getResolution(42)) .isEqualTo(DisplayResolutionTracker.RESOLUTION_QHD); } private static DisplayInfo makeDisplayInfo(int width, int height) { DisplayInfo info = new DisplayInfo(); info.logicalWidth = width; info.logicalHeight = height; return info; } }
core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java +11 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,7 @@ public class FrameTrackerTest { when(config.isSurfaceOnly()).thenReturn(surfaceOnly); when(config.getSurfaceControl()).thenReturn(mSurfaceControl); when(config.shouldDeferMonitor()).thenReturn(true); when(config.getDisplayId()).thenReturn(42); View view = mRule.getActivity().getWindow().getDecorView(); Handler spyHandler = spy(new Handler(handler.getLooper())); when(config.getView()).thenReturn(surfaceOnly ? null : view); Loading Loading @@ -168,6 +169,7 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -204,6 +206,7 @@ public class FrameTrackerTest { verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, Loading Loading @@ -240,6 +243,7 @@ public class FrameTrackerTest { verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -276,6 +280,7 @@ public class FrameTrackerTest { verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, Loading Loading @@ -315,6 +320,7 @@ public class FrameTrackerTest { verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, Loading Loading @@ -356,6 +362,7 @@ public class FrameTrackerTest { verify(tracker).removeObservers(); verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -483,6 +490,7 @@ public class FrameTrackerTest { verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(2L) /* totalFrames */, eq(1L) /* missedFrames */, Loading Loading @@ -519,6 +527,7 @@ public class FrameTrackerTest { verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -555,6 +564,7 @@ public class FrameTrackerTest { verify(tracker, never()).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(2L) /* totalFrames */, eq(0L) /* missedFrames */, Loading Loading @@ -585,6 +595,7 @@ public class FrameTrackerTest { verify(mSurfaceControlWrapper).removeJankStatsListener(any()); verify(tracker).triggerPerfetto(); verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED), eq(42), /* displayId */ eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]), eq(6L) /* totalFrames */, eq(5L) /* missedFrames */, Loading