diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl index d0e860c9109f181f2b6186506f55e54089d05a41..4c8f02da48f4108a9cbf728440c621e7e46cb9b4 100644 --- a/media/java/android/media/projection/IMediaProjectionManager.aidl +++ b/media/java/android/media/projection/IMediaProjectionManager.aidl @@ -193,4 +193,17 @@ interface IMediaProjectionManager { @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" + ".permission.MANAGE_MEDIA_PROJECTION)") oneway void notifyPermissionRequestInitiated(int hostUid, int sessionCreationSource); + + /** + * Notifies system server that the permission request was displayed. + * + * <p>Only used for emitting atoms. + * + * @param hostUid The uid of the process requesting consent to capture, may be an app or + * SystemUI. + */ + @EnforcePermission("android.Manifest.permission.MANAGE_MEDIA_PROJECTION") + @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest" + + ".permission.MANAGE_MEDIA_PROJECTION)") + oneway void notifyPermissionRequestDisplayed(int hostUid); } diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt index d8cab6ab2a6cf3936c7fd03c0c4bc50e2b1d5e82..a3820562a3d6d97e189e02f141d29b806e118965 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLogger.kt @@ -23,7 +23,6 @@ import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGE import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_CAST as METRICS_CREATION_SOURCE_CAST import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_SYSTEM_UI_SCREEN_RECORDER as METRICS_CREATION_SOURCE_SYSTEM_UI_SCREEN_RECORDER import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN as METRICS_CREATION_SOURCE_UNKNOWN -import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED as METRICS_STATE_PERMISSION_REQUEST_DISPLAYED import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject @@ -53,8 +52,17 @@ constructor(private val service: IMediaProjectionManager) { } } - fun notifyPermissionRequestDisplayed() { - notifyToServer(METRICS_STATE_PERMISSION_REQUEST_DISPLAYED, SessionCreationSource.UNKNOWN) + /** + * Request to log that the permission request was displayed. + * + * @param hostUid The UID of the package that initiates MediaProjection. + */ + fun notifyPermissionRequestDisplayed(hostUid: Int) { + try { + service.notifyPermissionRequestDisplayed(hostUid) + } catch (e: RemoteException) { + Log.e(TAG, "Error notifying server of projection displayed", e) + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java index 922f7e0aabaf7c38180db39b09da4693775ddc0f..72720f83e5aacb636f529fcce2f8f1c6ad3b1f5b 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java @@ -252,7 +252,7 @@ public class MediaProjectionPermissionActivity extends Activity mDialog.show(); if (savedInstanceState == null) { - mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed(); + mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed(mUid); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java index e27a59c6fb21e8300f6815a2a1ad866e5361eaa9..f37f58db05f887e92532af7f913580b9079b38bf 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java @@ -47,6 +47,7 @@ import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.res.R; import com.android.systemui.screenrecord.RecordingController; +import com.android.systemui.settings.UserContextProvider; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -71,6 +72,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> private final FeatureFlags mFlags; private final PanelInteractor mPanelInteractor; private final MediaProjectionMetricsLogger mMediaProjectionMetricsLogger; + private final UserContextProvider mUserContextProvider; private long mMillisUntilFinished = 0; @@ -91,7 +93,8 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> KeyguardStateController keyguardStateController, DialogLaunchAnimator dialogLaunchAnimator, PanelInteractor panelInteractor, - MediaProjectionMetricsLogger mediaProjectionMetricsLogger + MediaProjectionMetricsLogger mediaProjectionMetricsLogger, + UserContextProvider userContextProvider ) { super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); @@ -103,6 +106,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> mDialogLaunchAnimator = dialogLaunchAnimator; mPanelInteractor = panelInteractor; mMediaProjectionMetricsLogger = mediaProjectionMetricsLogger; + mUserContextProvider = userContextProvider; } @Override @@ -195,7 +199,8 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> dialog.show(); } - mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed(); + int uid = mUserContextProvider.getUserContext().getUserId(); + mMediaProjectionMetricsLogger.notifyPermissionRequestDisplayed(uid); return false; }; diff --git a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt index 429aad113a9a414e7ebdfb26b69fa8453ebb217c..347ed56667b8737b7ee142905c84c8f75c678c3c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/mediaprojection/MediaProjectionMetricsLoggerTest.kt @@ -63,4 +63,13 @@ class MediaProjectionMetricsLoggerTest : SysuiTestCase() { verify(service).notifyPermissionRequestInitiated(hostUid, METRICS_CREATION_SOURCE_UNKNOWN) } + + @Test + fun notifyPermissionRequestDisplayed_forwardsToService() { + val hostUid = 987 + + logger.notifyPermissionRequestDisplayed(hostUid) + + verify(service).notifyPermissionRequestDisplayed(hostUid) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java index ac03073be17badea38dfe202929324b73ed80a20..c6d156f519053e35e86dd4b433527967bc57295b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java @@ -52,6 +52,7 @@ import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.res.R; import com.android.systemui.screenrecord.RecordingController; +import com.android.systemui.settings.UserContextProvider; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -96,6 +97,8 @@ public class ScreenRecordTileTest extends SysuiTestCase { private MediaProjectionMetricsLogger mMediaProjectionMetricsLogger; @Mock private Dialog mPermissionDialogPrompt; + @Mock + private UserContextProvider mUserContextProvider; private TestableLooper mTestableLooper; private ScreenRecordTile mTile; @@ -106,6 +109,7 @@ public class ScreenRecordTileTest extends SysuiTestCase { mTestableLooper = TestableLooper.get(this); + when(mUserContextProvider.getUserContext()).thenReturn(mContext); when(mHost.getContext()).thenReturn(mContext); mTile = new ScreenRecordTile( @@ -124,7 +128,8 @@ public class ScreenRecordTileTest extends SysuiTestCase { mKeyguardStateController, mDialogLaunchAnimator, mPanelInteractor, - mMediaProjectionMetricsLogger + mMediaProjectionMetricsLogger, + mUserContextProvider ); mTile.initialize(); @@ -308,7 +313,8 @@ public class ScreenRecordTileTest extends SysuiTestCase { onDismissAction.getValue().onDismiss(); verify(mPermissionDialogPrompt).show(); - verify(mMediaProjectionMetricsLogger).notifyPermissionRequestDisplayed(); + verify(mMediaProjectionMetricsLogger) + .notifyPermissionRequestDisplayed(mContext.getUserId()); } } diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index ce35a61143893e5a1fab2e110dc85ffac96307f2..da1724d835a5ce618e0a0510559ddeb71186fcc9 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -76,7 +76,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; -import com.android.internal.util.FrameworkStatsLog; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.Watchdog; @@ -385,10 +384,12 @@ public final class MediaProjectionManagerService extends SystemService if (mProjectionGrant != null) { // Cache the session details. mProjectionGrant.mSession = incomingSession; - mMediaProjectionMetricsLogger.notifyProjectionStateChange( - mProjectionGrant.uid, - FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS, - FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + if (incomingSession != null) { + // Only log in progress when session is not null. + // setContentRecordingSession is called with a null session for the stop case. + mMediaProjectionMetricsLogger.logInProgress( + mProjectionGrant.uid, incomingSession.getTargetUid()); + } dispatchSessionSet(mProjectionGrant.getProjectionInfo(), incomingSession); } return true; @@ -463,6 +464,11 @@ public final class MediaProjectionManagerService extends SystemService mMediaProjectionMetricsLogger.logInitiated(hostUid, sessionCreationSource); } + @VisibleForTesting + void notifyPermissionRequestDisplayed(int hostUid) { + mMediaProjectionMetricsLogger.logPermissionRequestDisplayed(hostUid); + } + /** * Handles result of dialog shown from * {@link BinderService#buildReviewGrantedConsentIntentLocked()}. @@ -865,6 +871,18 @@ public final class MediaProjectionManagerService extends SystemService } } + @Override // Binder call + @EnforcePermission(MANAGE_MEDIA_PROJECTION) + public void notifyPermissionRequestDisplayed(int hostUid) { + notifyPermissionRequestDisplayed_enforcePermission(); + final long token = Binder.clearCallingIdentity(); + try { + MediaProjectionManagerService.this.notifyPermissionRequestDisplayed(hostUid); + } finally { + Binder.restoreCallingIdentity(token); + } + } + @Override // Binder call public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java b/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java index c8b932ab6ccc748910670af425cb42591d0e4bbd..aee0b31447c369a29956f4888c71828a3ac31bf3 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionMetricsLogger.java @@ -16,6 +16,12 @@ package com.android.server.media.projection; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED; + import android.content.Context; import com.android.internal.util.FrameworkStatsLog; @@ -82,25 +88,59 @@ public class MediaProjectionMetricsLogger { : (int) durationSinceLastActiveSession.toSeconds(); write( mSessionIdGenerator.createAndGetNewSessionId(), - FrameworkStatsLog - .MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED, + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED, hostUid, TARGET_UID_UNKNOWN, timeSinceLastActiveInSeconds, sessionCreationSource); } - /** Logs that the capturing stopped, either normally or because of error. */ + /** + * Logs that the user entered the setup flow and permission dialog is displayed. This state is + * not sent when the permission is already granted and we skipped showing the permission dialog. + * + * @param hostUid UID of the package that initiates MediaProjection. + */ + public void logPermissionRequestDisplayed(int hostUid) { + write( + mSessionIdGenerator.getCurrentSessionId(), + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED, + hostUid, + TARGET_UID_UNKNOWN, + TIME_SINCE_LAST_ACTIVE_UNKNOWN, + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + } + + /** + * Logs that the virtual display is created and capturing the selected region begins. + * + * @param hostUid UID of the package that initiates MediaProjection. + * @param targetUid UID of the package that is captured if selected. + */ + public void logInProgress(int hostUid, int targetUid) { + write( + mSessionIdGenerator.getCurrentSessionId(), + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS, + hostUid, + targetUid, + TIME_SINCE_LAST_ACTIVE_UNKNOWN, + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + } + + /** + * Logs that the capturing stopped, either normally or because of error. + * + * @param hostUid UID of the package that initiates MediaProjection. + * @param targetUid UID of the package that is captured if selected. + */ public void logStopped(int hostUid, int targetUid) { write( mSessionIdGenerator.getCurrentSessionId(), - FrameworkStatsLog - .MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED, + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED, hostUid, targetUid, TIME_SINCE_LAST_ACTIVE_UNKNOWN, - FrameworkStatsLog - .MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); mTimestampStore.registerActiveSessionEnded(); } diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java index 9f6d7f223716ad3fe2c7fb64ccf63e8fc5b60d2a..fbf21c5b06c69cc61a6547cc59c0ddc8cc0ae12e 100644 --- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java @@ -26,11 +26,10 @@ import static android.media.projection.ReviewGrantedConsentResult.UNKNOWN; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; -import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS; - import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; @@ -69,7 +68,6 @@ import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.internal.util.FrameworkStatsLog; import com.android.server.LocalServices; import com.android.server.testutils.OffsettableClock; import com.android.server.wm.WindowManagerInternal; @@ -664,6 +662,17 @@ public class MediaProjectionManagerServiceTest { verify(mMediaProjectionMetricsLogger).logInitiated(hostUid, sessionCreationSource); } + @Test + public void notifyPermissionRequestDisplayed_forwardsToLogger() { + int hostUid = 123; + mService = + new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector); + + mService.notifyPermissionRequestDisplayed(hostUid); + + verify(mMediaProjectionMetricsLogger).logPermissionRequestDisplayed(hostUid); + } + /** * Executes and validates scenario where the consent result indicates the projection ends. */ @@ -837,10 +846,69 @@ public class MediaProjectionManagerServiceTest { service.setContentRecordingSession(DISPLAY_SESSION); - verify(mMediaProjectionMetricsLogger).notifyProjectionStateChange( + verify(mMediaProjectionMetricsLogger).logInProgress( projection.uid, - MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS, - FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN + DISPLAY_SESSION.getTargetUid() + ); + } + + @Test + public void setContentRecordingSession_taskSession_logsCaptureInProgressWithTargetUid() + throws Exception { + mService.addCallback(mWatcherCallback); + MediaProjectionManagerService service = + new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector); + MediaProjectionManagerService.MediaProjection projection = + startProjectionPreconditions(service); + projection.start(mIMediaProjectionCallback); + doReturn(true) + .when(mWindowManagerInternal) + .setContentRecordingSession(any(ContentRecordingSession.class)); + int targetUid = 123455; + + ContentRecordingSession taskSession = + ContentRecordingSession.createTaskSession(mock(IBinder.class), targetUid); + service.setContentRecordingSession(taskSession); + + verify(mMediaProjectionMetricsLogger).logInProgress(projection.uid, targetUid); + } + + @Test + public void setContentRecordingSession_failure_doesNotLogCaptureInProgress() throws Exception { + mService.addCallback(mWatcherCallback); + MediaProjectionManagerService service = + new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector); + MediaProjectionManagerService.MediaProjection projection = + startProjectionPreconditions(service); + projection.start(mIMediaProjectionCallback); + doReturn(false).when(mWindowManagerInternal).setContentRecordingSession( + any(ContentRecordingSession.class)); + + service.setContentRecordingSession(DISPLAY_SESSION); + + verify(mMediaProjectionMetricsLogger, never()).logInProgress( + anyInt(), + anyInt() + ); + } + + @Test + public void setContentRecordingSession_sessionNull_doesNotLogCaptureInProgress() + throws Exception { + mService.addCallback(mWatcherCallback); + MediaProjectionManagerService service = + new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector); + MediaProjectionManagerService.MediaProjection projection = + startProjectionPreconditions(service); + projection.start(mIMediaProjectionCallback); + doReturn(true).when(mWindowManagerInternal).setContentRecordingSession( + any(ContentRecordingSession.class)); + + service.setContentRecordingSession(null); + + verify(mMediaProjectionMetricsLogger, never()).logInProgress( + anyInt(), + anyInt() ); } diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java index 73b4cc8cc59298b4fab88598118de2156ab9a9c7..8ba3ac90ee828245e68a8959cac750859f33235b 100644 --- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java +++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionMetricsLoggerTest.java @@ -17,7 +17,9 @@ package com.android.server.media.projection; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED; +import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED; import static com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN; @@ -233,6 +235,152 @@ public class MediaProjectionMetricsLoggerTest { inOrder.verify(mTimestampStore).registerActiveSessionEnded(); } + @Test + public void logInProgress_logsStateChangedAtomId() { + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + + verifyStateChangedAtomIdLogged(); + } + + @Test + public void logInProgress_logsCurrentSessionId() { + int currentSessionId = 987; + when(mSessionIdGenerator.getCurrentSessionId()).thenReturn(currentSessionId); + + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + + verifySessionIdLogged(currentSessionId); + } + + @Test + public void logInProgress_logsStateInProgress() { + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + + verifyStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS); + } + + @Test + public void logInProgress_logsHostUid() { + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + + verifyHostUidLogged(TEST_HOST_UID); + } + + @Test + public void logInProgress_logsTargetUid() { + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + + verifyTargetUidLogged(TEST_TARGET_UID); + } + + @Test + public void logInProgress_logsUnknownTimeSinceLastActive() { + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + + verifyTimeSinceLastActiveSessionLogged(-1); + } + + @Test + public void logInProgress_logsUnknownSessionCreationSource() { + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + + verifyCreationSourceLogged( + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + } + + @Test + public void logInProgress_logsPreviousState() { + mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE); + verifyPreviousStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN); + + mLogger.logInProgress(TEST_HOST_UID, TEST_TARGET_UID); + verifyPreviousStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED); + + mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE); + verifyPreviousStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_CAPTURING_IN_PROGRESS); + + mLogger.logInProgress(TEST_HOST_UID, TEST_CREATION_SOURCE); + verifyPreviousStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED); + } + + @Test + public void logPermissionRequestDisplayed_logsStateChangedAtomId() { + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + + verifyStateChangedAtomIdLogged(); + } + + @Test + public void logPermissionRequestDisplayed_logsCurrentSessionId() { + int currentSessionId = 765; + when(mSessionIdGenerator.getCurrentSessionId()).thenReturn(currentSessionId); + + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + + verifySessionIdLogged(currentSessionId); + } + + @Test + public void logPermissionRequestDisplayed_logsStateDisplayed() { + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + + verifyStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED); + } + + @Test + public void logPermissionRequestDisplayed_logsHostUid() { + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + + verifyHostUidLogged(TEST_HOST_UID); + } + + @Test + public void logPermissionRequestDisplayed_logsUnknownTargetUid() { + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + + verifyTargetUidLogged(-2); + } + + @Test + public void logPermissionRequestDisplayed_logsUnknownTimeSinceLastActive() { + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + + verifyTimeSinceLastActiveSessionLogged(-1); + } + + @Test + public void logPermissionRequestDisplayed_logsUnknownSessionCreationSource() { + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + + verifyCreationSourceLogged( + MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_UNKNOWN); + } + + @Test + public void logPermissionRequestDisplayed_logsPreviousState() { + mLogger.logInitiated(TEST_HOST_UID, TEST_CREATION_SOURCE); + verifyPreviousStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN); + + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + verifyPreviousStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED); + + mLogger.logStopped(TEST_HOST_UID, TEST_CREATION_SOURCE); + verifyPreviousStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_PERMISSION_REQUEST_DISPLAYED); + + mLogger.logPermissionRequestDisplayed(TEST_HOST_UID); + verifyPreviousStateLogged( + MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_STOPPED); + } + private void verifyStateChangedAtomIdLogged() { verify(mFrameworkStatsLogWrapper) .write(