Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44459dd8 authored by Chris Göllner's avatar Chris Göllner Committed by Android (Google) Code Review
Browse files

Merge changes Ic6a5e826,Icf29201b into main

* changes:
  [Media Projection] Logs STATE_STOPPED
  [Media Projection] Implement server side logging of STATE_INITIATED
parents c91700a7 359bdc62
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -176,4 +176,21 @@ interface IMediaProjectionManager {
    @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
            + ".permission.MANAGE_MEDIA_PROJECTION)")
    oneway void notifyPermissionRequestStateChange(int hostUid, int state, int sessionCreationSource);

    /**
     * Notifies system server that the permission request was initiated.
     *
     * <p>Only used for emitting atoms.
     *
     * @param hostUid               The uid of the process requesting consent to capture, may be an app or
     *                              SystemUI.
     * @param sessionCreationSource Only set if the state is MEDIA_PROJECTION_STATE_INITIATED.
     *                              Indicates the entry point for requesting the permission. Must be
     *                              a valid state defined
     *                              in the SessionCreationSource enum.
     */
    @EnforcePermission("android.Manifest.permission.MANAGE_MEDIA_PROJECTION")
    @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
            + ".permission.MANAGE_MEDIA_PROJECTION)")
    oneway void notifyPermissionRequestInitiated(int hostUid, int sessionCreationSource);
}
+11 −6
Original line number Diff line number Diff line
@@ -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_INITIATED
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
@@ -36,16 +35,22 @@ import javax.inject.Inject
class MediaProjectionMetricsLogger
@Inject
constructor(private val service: IMediaProjectionManager) {

    /**
     * Request to log that the permission was requested.
     *
     * @param hostUid The UID of the package that initiates MediaProjection.
     * @param sessionCreationSource The entry point requesting permission to capture.
     */
    fun notifyProjectionInitiated(sessionCreationSource: SessionCreationSource) {
        notifyToServer(
            MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED,
            sessionCreationSource
    fun notifyProjectionInitiated(hostUid: Int, sessionCreationSource: SessionCreationSource) {
        try {
            service.notifyPermissionRequestInitiated(
                hostUid,
                sessionCreationSource.toMetricsConstant()
            )
        } catch (e: RemoteException) {
            Log.e(TAG, "Error notifying server of projection initiated", e)
        }
    }

    fun notifyPermissionRequestDisplayed() {
+2 −1
Original line number Diff line number Diff line
@@ -140,7 +140,7 @@ public class MediaProjectionPermissionActivity extends Activity
            if (MediaProjectionServiceHelper.hasProjectionPermission(mUid, mPackageName)) {
                if (savedInstanceState == null) {
                    mMediaProjectionMetricsLogger.notifyProjectionInitiated(
                            SessionCreationSource.APP);
                            mUid, SessionCreationSource.APP);
                }
                final IMediaProjection projection =
                        MediaProjectionServiceHelper.createOrReuseProjection(mUid, mPackageName,
@@ -242,6 +242,7 @@ public class MediaProjectionPermissionActivity extends Activity

        if (savedInstanceState == null) {
            mMediaProjectionMetricsLogger.notifyProjectionInitiated(
                    mUid,
                    appName == null
                            ? SessionCreationSource.CAST
                            : SessionCreationSource.APP);
+1 −0
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@ public class RecordingController
        }

        mMediaProjectionMetricsLogger.notifyProjectionInitiated(
                mUserContextProvider.getUserContext().getUserId(),
                SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER);

        return flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)
+66 −0
Original line number Diff line number Diff line
package com.android.systemui.mediaprojection

import android.media.projection.IMediaProjectionManager
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__CREATION_SOURCE__CREATION_SOURCE_APP as METRICS_CREATION_SOURCE_APP
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.systemui.SysuiTestCase
import com.android.systemui.util.mockito.mock
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.verify

@RunWith(AndroidTestingRunner::class)
@SmallTest
class MediaProjectionMetricsLoggerTest : SysuiTestCase() {

    private val service = mock<IMediaProjectionManager>()
    private val logger = MediaProjectionMetricsLogger(service)

    @Test
    fun notifyProjectionInitiated_sourceApp_forwardsToServiceWithMetricsValue() {
        val hostUid = 123
        val sessionCreationSource = SessionCreationSource.APP

        logger.notifyProjectionInitiated(hostUid, sessionCreationSource)

        verify(service).notifyPermissionRequestInitiated(hostUid, METRICS_CREATION_SOURCE_APP)
    }

    @Test
    fun notifyProjectionInitiated_sourceCast_forwardsToServiceWithMetricsValue() {
        val hostUid = 123
        val sessionCreationSource = SessionCreationSource.CAST

        logger.notifyProjectionInitiated(hostUid, sessionCreationSource)

        verify(service).notifyPermissionRequestInitiated(hostUid, METRICS_CREATION_SOURCE_CAST)
    }

    @Test
    fun notifyProjectionInitiated_sourceSysUI_forwardsToServiceWithMetricsValue() {
        val hostUid = 123
        val sessionCreationSource = SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER

        logger.notifyProjectionInitiated(hostUid, sessionCreationSource)

        verify(service)
            .notifyPermissionRequestInitiated(
                hostUid,
                METRICS_CREATION_SOURCE_SYSTEM_UI_SCREEN_RECORDER
            )
    }

    @Test
    fun notifyProjectionInitiated_sourceUnknown_forwardsToServiceWithMetricsValue() {
        val hostUid = 123
        val sessionCreationSource = SessionCreationSource.UNKNOWN

        logger.notifyProjectionInitiated(hostUid, sessionCreationSource)

        verify(service).notifyPermissionRequestInitiated(hostUid, METRICS_CREATION_SOURCE_UNKNOWN)
    }
}
Loading