Skip to content
Snippets Groups Projects
Commit 7b35eb95 authored by Sam Cackett's avatar Sam Cackett Committed by Android (Google) Code Review
Browse files

Merge "[PartialScreenShare] Add tracking for media projection initiated" into main

parents 57cb73f2 485fa22d
No related branches found
No related tags found
No related merge requests found
......@@ -175,5 +175,5 @@ interface IMediaProjectionManager {
@EnforcePermission("android.Manifest.permission.MANAGE_MEDIA_PROJECTION")
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
void notifyPermissionRequestStateChange(int hostUid, int state, int sessionCreationSource);
oneway void notifyPermissionRequestStateChange(int hostUid, int state, int sessionCreationSource);
}
......@@ -19,7 +19,11 @@ import android.media.projection.IMediaProjectionManager
import android.os.Process
import android.os.RemoteException
import android.util.Log
import com.android.internal.util.FrameworkStatsLog
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.internal.util.FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
......@@ -36,21 +40,23 @@ constructor(private val service: IMediaProjectionManager) {
*
* @param sessionCreationSource The entry point requesting permission to capture.
*/
fun notifyPermissionProgress(state: Int, sessionCreationSource: Int) {
// TODO check that state & SessionCreationSource matches expected values
notifyToServer(state, sessionCreationSource)
fun notifyProjectionInitiated(sessionCreationSource: SessionCreationSource) {
notifyToServer(
MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_INITIATED,
sessionCreationSource
)
}
/**
* Request to log that the permission request moved to the given state.
*
* Should not be used for the initialization state, since that
* Should not be used for the initialization state, since that should use {@link
* MediaProjectionMetricsLogger#notifyProjectionInitiated(Int)} and pass the
* sessionCreationSource.
*/
fun notifyPermissionProgress(state: Int) {
// TODO validate state is valid
notifyToServer(
state,
FrameworkStatsLog.MEDIA_PROJECTION_STATE_CHANGED__STATE__MEDIA_PROJECTION_STATE_UNKNOWN)
notifyToServer(state, SessionCreationSource.UNKNOWN)
}
/**
......@@ -64,16 +70,21 @@ constructor(private val service: IMediaProjectionManager) {
* Indicates the entry point for requesting the permission. Must be a valid state defined in
* the SessionCreationSource enum.
*/
private fun notifyToServer(state: Int, sessionCreationSource: Int) {
private fun notifyToServer(state: Int, sessionCreationSource: SessionCreationSource) {
Log.v(TAG, "FOO notifyToServer of state $state and source $sessionCreationSource")
try {
service.notifyPermissionRequestStateChange(
Process.myUid(), state, sessionCreationSource)
Process.myUid(),
state,
sessionCreationSource.toMetricsConstant()
)
} catch (e: RemoteException) {
Log.e(
TAG,
"Error notifying server of permission flow state $state from source $sessionCreationSource",
e)
"Error notifying server of permission flow state $state from source " +
"$sessionCreationSource",
e
)
}
}
......@@ -81,3 +92,18 @@ constructor(private val service: IMediaProjectionManager) {
const val TAG = "MediaProjectionMetricsLogger"
}
}
enum class SessionCreationSource {
APP,
CAST,
SYSTEM_UI_SCREEN_RECORDER,
UNKNOWN;
fun toMetricsConstant(): Int =
when (this) {
APP -> METRICS_CREATION_SOURCE_APP
CAST -> METRICS_CREATION_SOURCE_CAST
SYSTEM_UI_SCREEN_RECORDER -> METRICS_CREATION_SOURCE_SYSTEM_UI_SCREEN_RECORDER
UNKNOWN -> METRICS_CREATION_SOURCE_UNKNOWN
}
}
......@@ -53,7 +53,9 @@ import android.view.Window;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger;
import com.android.systemui.mediaprojection.MediaProjectionServiceHelper;
import com.android.systemui.mediaprojection.SessionCreationSource;
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog;
......@@ -74,6 +76,7 @@ public class MediaProjectionPermissionActivity extends Activity
private final FeatureFlags mFeatureFlags;
private final Lazy<ScreenCaptureDevicePolicyResolver> mScreenCaptureDevicePolicyResolver;
private final StatusBarManager mStatusBarManager;
private final MediaProjectionMetricsLogger mMediaProjectionMetricsLogger;
private String mPackageName;
private int mUid;
......@@ -90,15 +93,17 @@ public class MediaProjectionPermissionActivity extends Activity
@Inject
public MediaProjectionPermissionActivity(FeatureFlags featureFlags,
Lazy<ScreenCaptureDevicePolicyResolver> screenCaptureDevicePolicyResolver,
StatusBarManager statusBarManager) {
StatusBarManager statusBarManager,
MediaProjectionMetricsLogger mediaProjectionMetricsLogger) {
mFeatureFlags = featureFlags;
mScreenCaptureDevicePolicyResolver = screenCaptureDevicePolicyResolver;
mStatusBarManager = statusBarManager;
mMediaProjectionMetricsLogger = mediaProjectionMetricsLogger;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent launchingIntent = getIntent();
mReviewGrantedConsentRequired = launchingIntent.getBooleanExtra(
......@@ -133,6 +138,10 @@ public class MediaProjectionPermissionActivity extends Activity
try {
if (MediaProjectionServiceHelper.hasProjectionPermission(mUid, mPackageName)) {
if (savedInstanceState == null) {
mMediaProjectionMetricsLogger.notifyProjectionInitiated(
SessionCreationSource.APP);
}
final IMediaProjection projection =
MediaProjectionServiceHelper.createOrReuseProjection(mUid, mPackageName,
mReviewGrantedConsentRequired);
......@@ -231,6 +240,13 @@ public class MediaProjectionPermissionActivity extends Activity
mDialog = dialogBuilder.create();
}
if (savedInstanceState == null) {
mMediaProjectionMetricsLogger.notifyProjectionInitiated(
appName == null
? SessionCreationSource.CAST
: SessionCreationSource.APP);
}
setUpDialog(mDialog);
mDialog.show();
}
......
......@@ -38,6 +38,8 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger;
import com.android.systemui.mediaprojection.SessionCreationSource;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog;
import com.android.systemui.plugins.ActivityStarter;
......@@ -45,13 +47,13 @@ import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.CallbackController;
import dagger.Lazy;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import dagger.Lazy;
/**
* Helper class to initiate a screen recording
*/
......@@ -71,6 +73,7 @@ public class RecordingController
private final FeatureFlags mFlags;
private final UserContextProvider mUserContextProvider;
private final UserTracker mUserTracker;
private final MediaProjectionMetricsLogger mMediaProjectionMetricsLogger;
protected static final String INTENT_UPDATE_STATE =
"com.android.systemui.screenrecord.UPDATE_STATE";
......@@ -115,7 +118,8 @@ public class RecordingController
FeatureFlags flags,
UserContextProvider userContextProvider,
Lazy<ScreenCaptureDevicePolicyResolver> devicePolicyResolver,
UserTracker userTracker) {
UserTracker userTracker,
MediaProjectionMetricsLogger mediaProjectionMetricsLogger) {
mMainExecutor = mainExecutor;
mContext = context;
mFlags = flags;
......@@ -123,6 +127,7 @@ public class RecordingController
mBroadcastDispatcher = broadcastDispatcher;
mUserContextProvider = userContextProvider;
mUserTracker = userTracker;
mMediaProjectionMetricsLogger = mediaProjectionMetricsLogger;
BroadcastOptions options = BroadcastOptions.makeBasic();
options.setInteractive(true);
......@@ -149,6 +154,9 @@ public class RecordingController
return new ScreenCaptureDisabledDialog(mContext);
}
mMediaProjectionMetricsLogger.notifyProjectionInitiated(
SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER);
return flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)
? new ScreenRecordPermissionDialog(context, getHostUserHandle(), this,
activityStarter, mUserContextProvider, onStartRecordingClicked)
......
......@@ -17,8 +17,10 @@
package com.android.systemui.screenrecord;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
......@@ -37,6 +39,8 @@ import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger;
import com.android.systemui.mediaprojection.SessionCreationSource;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver;
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog;
import com.android.systemui.plugins.ActivityStarter;
......@@ -76,6 +80,8 @@ public class RecordingControllerTest extends SysuiTestCase {
private ActivityStarter mActivityStarter;
@Mock
private UserTracker mUserTracker;
@Mock
private MediaProjectionMetricsLogger mMediaProjectionMetricsLogger;
private FakeFeatureFlags mFeatureFlags;
private RecordingController mController;
......@@ -86,8 +92,15 @@ public class RecordingControllerTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
mFeatureFlags = new FakeFeatureFlags();
mController = new RecordingController(mMainExecutor, mBroadcastDispatcher, mContext,
mFeatureFlags, mUserContextProvider, () -> mDevicePolicyResolver, mUserTracker);
mController = new RecordingController(
mMainExecutor,
mBroadcastDispatcher,
mContext,
mFeatureFlags,
mUserContextProvider,
() -> mDevicePolicyResolver,
mUserTracker,
mMediaProjectionMetricsLogger);
mController.addCallback(mCallback);
}
......@@ -269,4 +282,21 @@ public class RecordingControllerTest extends SysuiTestCase {
assertThat(dialog).isInstanceOf(ScreenRecordPermissionDialog.class);
}
@Test
public void testPoliciesFlagEnabled_screenCapturingAllowed_logsProjectionInitiated() {
if (Looper.myLooper() == null) {
Looper.prepare();
}
mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, true);
mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, true);
when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(false);
mController.createScreenRecordDialog(mContext, mFeatureFlags,
mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null);
verify(mMediaProjectionMetricsLogger)
.notifyProjectionInitiated(SessionCreationSource.SYSTEM_UI_SCREEN_RECORDER);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment