Loading packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java +23 −28 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISSED_OTHER; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISS_TAPPED; Loading @@ -41,7 +42,6 @@ import android.app.RemoteAction; import android.content.BroadcastReceiver; import android.content.ClipData; import android.content.ClipDescription; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; Loading @@ -51,7 +51,6 @@ import android.graphics.Bitmap; import android.hardware.display.DisplayManager; import android.hardware.input.InputManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Looper; import android.provider.DeviceConfig; import android.text.TextUtils; Loading @@ -62,10 +61,6 @@ import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.InputMonitor; import android.view.MotionEvent; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import androidx.annotation.NonNull; Loading @@ -74,12 +69,13 @@ import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule.OverlayWindowContext; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.screenshot.TimeoutHandler; import java.io.IOException; import java.util.ArrayList; import java.util.Optional; import java.util.concurrent.Executor; import javax.inject.Inject; Loading @@ -102,9 +98,9 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv private final DisplayManager mDisplayManager; private final ClipboardOverlayWindow mWindow; private final TimeoutHandler mTimeoutHandler; private final TextClassifier mTextClassifier; private final ClipboardOverlayUtils mClipboardUtils; private final FeatureFlags mFeatureFlags; private final Executor mBgExecutor; private final ClipboardOverlayView mView; Loading Loading @@ -189,6 +185,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv TimeoutHandler timeoutHandler, FeatureFlags featureFlags, ClipboardOverlayUtils clipboardUtils, @Background Executor bgExecutor, UiEventLogger uiEventLogger) { mBroadcastDispatcher = broadcastDispatcher; mDisplayManager = requireNonNull(context.getSystemService(DisplayManager.class)); Loading @@ -204,14 +201,12 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv hideImmediate(); }); mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class)) .getTextClassifier(); mTimeoutHandler = timeoutHandler; mTimeoutHandler.setDefaultTimeoutMillis(CLIPBOARD_DEFAULT_TIMEOUT_MILLIS); mFeatureFlags = featureFlags; mClipboardUtils = clipboardUtils; mBgExecutor = bgExecutor; mView.setCallbacks(mClipboardCallbacks); Loading Loading @@ -281,7 +276,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv if (isRemote || DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_SHOW_ACTIONS, false)) { if (item.getTextLinks() != null) { AsyncTask.execute(() -> classifyText(clipData.getItemAt(0), clipSource)); classifyText(clipData.getItemAt(0), clipSource); } } if (isSensitive) { Loading Loading @@ -338,22 +333,18 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv } private void classifyText(ClipData.Item item, String source) { ArrayList<RemoteAction> actions = new ArrayList<>(); for (TextLinks.TextLink link : item.getTextLinks().getLinks()) { TextClassification classification = mTextClassifier.classifyText( item.getText(), link.getStart(), link.getEnd(), null); actions.addAll(classification.getActions()); } mBgExecutor.execute(() -> { Optional<RemoteAction> action = mClipboardUtils.getAction(item, source); mView.post(() -> { Optional<RemoteAction> action = actions.stream().filter(remoteAction -> { ComponentName component = remoteAction.getActionIntent().getIntent().getComponent(); return component != null && !TextUtils.equals(source, component.getPackageName()); }).findFirst(); mView.resetActionChips(); action.ifPresent(remoteAction -> mView.setActionChip(remoteAction, () -> { action.ifPresent(remoteAction -> { mView.setActionChip(remoteAction, () -> { mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED); animateOut(); })); }); mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_ACTION_SHOWN); }); }); }); } Loading Loading @@ -539,6 +530,10 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv mClipSource = clipSource; } void logUnguarded(@NonNull UiEventLogger.UiEventEnum event) { mUiEventLogger.log(event, 0, mClipSource); } void logSessionComplete(@NonNull UiEventLogger.UiEventEnum event) { if (!mGuarded) { mGuarded = true; Loading packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java +2 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ public enum ClipboardOverlayEvent implements UiEventLogger.UiEventEnum { CLIPBOARD_OVERLAY_EDIT_TAPPED(951), @UiEvent(doc = "clipboard share tapped") CLIPBOARD_OVERLAY_SHARE_TAPPED(1067), @UiEvent(doc = "clipboard smart action shown") CLIPBOARD_OVERLAY_ACTION_SHOWN(1260), @UiEvent(doc = "clipboard action tapped") CLIPBOARD_OVERLAY_ACTION_TAPPED(952), @UiEvent(doc = "clipboard remote copy tapped") Loading packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java +30 −1 Original line number Diff line number Diff line Loading @@ -16,22 +16,34 @@ package com.android.systemui.clipboardoverlay; import android.app.RemoteAction; import android.content.ClipData; import android.content.ClipDescription; import android.content.ComponentName; import android.content.Context; import android.os.Build; import android.provider.DeviceConfig; import android.text.TextUtils; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.systemui.R; import java.util.ArrayList; import java.util.Optional; import javax.inject.Inject; class ClipboardOverlayUtils { private final TextClassifier mTextClassifier; @Inject ClipboardOverlayUtils() { ClipboardOverlayUtils(TextClassificationManager textClassificationManager) { mTextClassifier = textClassificationManager.getTextClassifier(); } boolean isRemoteCopy(Context context, ClipData clipData, String clipSource) { Loading @@ -52,4 +64,21 @@ class ClipboardOverlayUtils { } return false; } public Optional<RemoteAction> getAction(ClipData.Item item, String source) { return getActions(item).stream().filter(remoteAction -> { ComponentName component = remoteAction.getActionIntent().getIntent().getComponent(); return component != null && !TextUtils.equals(source, component.getPackageName()); }).findFirst(); } private ArrayList<RemoteAction> getActions(ClipData.Item item) { ArrayList<RemoteAction> actions = new ArrayList<>(); for (TextLinks.TextLink link : item.getTextLinks().getLinks()) { TextClassification classification = mTextClassifier.classifyText( item.getText(), link.getStart(), link.getEnd(), null); actions.addAll(classification.getActions()); } return actions; } } packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +7 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.CaptioningManager; import android.view.inputmethod.InputMethodManager; import android.view.textclassifier.TextClassificationManager; import androidx.core.app.NotificationManagerCompat; Loading Loading @@ -631,4 +632,10 @@ public class FrameworkServicesModule { static BluetoothAdapter provideBluetoothAdapter(BluetoothManager bluetoothManager) { return bluetoothManager.getAdapter(); } @Provides @Singleton static TextClassificationManager provideTextClassificationManager(Context context) { return context.getSystemService(TextClassificationManager.class); } } packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package com.android.systemui.clipboardoverlay; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISS_TAPPED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHARE_TAPPED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED; import static com.android.systemui.flags.Flags.CLIPBOARD_REMOTE_BEHAVIOR; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; Loading @@ -29,10 +31,13 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.animation.Animator; import android.app.RemoteAction; import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.net.Uri; import android.os.PersistableBundle; import android.view.textclassifier.TextLinks; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; Loading @@ -42,6 +47,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.screenshot.TimeoutHandler; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; import org.junit.After; import org.junit.Before; Loading @@ -50,7 +57,12 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.util.Optional; @SmallTest @RunWith(AndroidJUnit4.class) Loading Loading @@ -80,6 +92,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { private ArgumentCaptor<ClipboardOverlayView.ClipboardOverlayCallbacks> mOverlayCallbacksCaptor; private ClipboardOverlayView.ClipboardOverlayCallbacks mCallbacks; private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); @Before public void setup() { MockitoAnnotations.initMocks(this); Loading @@ -101,6 +115,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { mTimeoutHandler, mFeatureFlags, mClipboardUtils, mExecutor, mUiEventLogger); verify(mClipboardOverlayView).setCallbacks(mOverlayCallbacksCaptor.capture()); mCallbacks = mOverlayCallbacksCaptor.getValue(); Loading Loading @@ -237,4 +252,29 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED, 0, "second.package"); verifyNoMoreInteractions(mUiEventLogger); } @Test public void test_logOnClipboardActionsShown() { ClipData.Item item = mSampleClipData.getItemAt(0); item.setTextLinks(Mockito.mock(TextLinks.class)); mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true); when(mClipboardUtils.isRemoteCopy(any(Context.class), any(ClipData.class), anyString())) .thenReturn(true); when(mClipboardUtils.getAction(any(ClipData.Item.class), anyString())) .thenReturn(Optional.of(Mockito.mock(RemoteAction.class))); when(mClipboardOverlayView.post(any(Runnable.class))).thenAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { ((Runnable) invocation.getArgument(0)).run(); return null; } }); mOverlayController.setClipData( new ClipData(mSampleClipData.getDescription(), item), "actionShownSource"); mExecutor.runAllReady(); verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_ACTION_SHOWN, 0, "actionShownSource"); verifyNoMoreInteractions(mUiEventLogger); } } Loading
packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java +23 −28 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISSED_OTHER; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISS_TAPPED; Loading @@ -41,7 +42,6 @@ import android.app.RemoteAction; import android.content.BroadcastReceiver; import android.content.ClipData; import android.content.ClipDescription; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; Loading @@ -51,7 +51,6 @@ import android.graphics.Bitmap; import android.hardware.display.DisplayManager; import android.hardware.input.InputManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Looper; import android.provider.DeviceConfig; import android.text.TextUtils; Loading @@ -62,10 +61,6 @@ import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.InputMonitor; import android.view.MotionEvent; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import androidx.annotation.NonNull; Loading @@ -74,12 +69,13 @@ import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule.OverlayWindowContext; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.screenshot.TimeoutHandler; import java.io.IOException; import java.util.ArrayList; import java.util.Optional; import java.util.concurrent.Executor; import javax.inject.Inject; Loading @@ -102,9 +98,9 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv private final DisplayManager mDisplayManager; private final ClipboardOverlayWindow mWindow; private final TimeoutHandler mTimeoutHandler; private final TextClassifier mTextClassifier; private final ClipboardOverlayUtils mClipboardUtils; private final FeatureFlags mFeatureFlags; private final Executor mBgExecutor; private final ClipboardOverlayView mView; Loading Loading @@ -189,6 +185,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv TimeoutHandler timeoutHandler, FeatureFlags featureFlags, ClipboardOverlayUtils clipboardUtils, @Background Executor bgExecutor, UiEventLogger uiEventLogger) { mBroadcastDispatcher = broadcastDispatcher; mDisplayManager = requireNonNull(context.getSystemService(DisplayManager.class)); Loading @@ -204,14 +201,12 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv hideImmediate(); }); mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class)) .getTextClassifier(); mTimeoutHandler = timeoutHandler; mTimeoutHandler.setDefaultTimeoutMillis(CLIPBOARD_DEFAULT_TIMEOUT_MILLIS); mFeatureFlags = featureFlags; mClipboardUtils = clipboardUtils; mBgExecutor = bgExecutor; mView.setCallbacks(mClipboardCallbacks); Loading Loading @@ -281,7 +276,7 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv if (isRemote || DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_SHOW_ACTIONS, false)) { if (item.getTextLinks() != null) { AsyncTask.execute(() -> classifyText(clipData.getItemAt(0), clipSource)); classifyText(clipData.getItemAt(0), clipSource); } } if (isSensitive) { Loading Loading @@ -338,22 +333,18 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv } private void classifyText(ClipData.Item item, String source) { ArrayList<RemoteAction> actions = new ArrayList<>(); for (TextLinks.TextLink link : item.getTextLinks().getLinks()) { TextClassification classification = mTextClassifier.classifyText( item.getText(), link.getStart(), link.getEnd(), null); actions.addAll(classification.getActions()); } mBgExecutor.execute(() -> { Optional<RemoteAction> action = mClipboardUtils.getAction(item, source); mView.post(() -> { Optional<RemoteAction> action = actions.stream().filter(remoteAction -> { ComponentName component = remoteAction.getActionIntent().getIntent().getComponent(); return component != null && !TextUtils.equals(source, component.getPackageName()); }).findFirst(); mView.resetActionChips(); action.ifPresent(remoteAction -> mView.setActionChip(remoteAction, () -> { action.ifPresent(remoteAction -> { mView.setActionChip(remoteAction, () -> { mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED); animateOut(); })); }); mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_ACTION_SHOWN); }); }); }); } Loading Loading @@ -539,6 +530,10 @@ public class ClipboardOverlayController implements ClipboardListener.ClipboardOv mClipSource = clipSource; } void logUnguarded(@NonNull UiEventLogger.UiEventEnum event) { mUiEventLogger.log(event, 0, mClipSource); } void logSessionComplete(@NonNull UiEventLogger.UiEventEnum event) { if (!mGuarded) { mGuarded = true; Loading
packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java +2 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ public enum ClipboardOverlayEvent implements UiEventLogger.UiEventEnum { CLIPBOARD_OVERLAY_EDIT_TAPPED(951), @UiEvent(doc = "clipboard share tapped") CLIPBOARD_OVERLAY_SHARE_TAPPED(1067), @UiEvent(doc = "clipboard smart action shown") CLIPBOARD_OVERLAY_ACTION_SHOWN(1260), @UiEvent(doc = "clipboard action tapped") CLIPBOARD_OVERLAY_ACTION_TAPPED(952), @UiEvent(doc = "clipboard remote copy tapped") Loading
packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java +30 −1 Original line number Diff line number Diff line Loading @@ -16,22 +16,34 @@ package com.android.systemui.clipboardoverlay; import android.app.RemoteAction; import android.content.ClipData; import android.content.ClipDescription; import android.content.ComponentName; import android.content.Context; import android.os.Build; import android.provider.DeviceConfig; import android.text.TextUtils; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextLinks; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.systemui.R; import java.util.ArrayList; import java.util.Optional; import javax.inject.Inject; class ClipboardOverlayUtils { private final TextClassifier mTextClassifier; @Inject ClipboardOverlayUtils() { ClipboardOverlayUtils(TextClassificationManager textClassificationManager) { mTextClassifier = textClassificationManager.getTextClassifier(); } boolean isRemoteCopy(Context context, ClipData clipData, String clipSource) { Loading @@ -52,4 +64,21 @@ class ClipboardOverlayUtils { } return false; } public Optional<RemoteAction> getAction(ClipData.Item item, String source) { return getActions(item).stream().filter(remoteAction -> { ComponentName component = remoteAction.getActionIntent().getIntent().getComponent(); return component != null && !TextUtils.equals(source, component.getPackageName()); }).findFirst(); } private ArrayList<RemoteAction> getActions(ClipData.Item item) { ArrayList<RemoteAction> actions = new ArrayList<>(); for (TextLinks.TextLink link : item.getTextLinks().getLinks()) { TextClassification classification = mTextClassifier.classifyText( item.getText(), link.getStart(), link.getEnd(), null); actions.addAll(classification.getActions()); } return actions; } }
packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +7 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.CaptioningManager; import android.view.inputmethod.InputMethodManager; import android.view.textclassifier.TextClassificationManager; import androidx.core.app.NotificationManagerCompat; Loading Loading @@ -631,4 +632,10 @@ public class FrameworkServicesModule { static BluetoothAdapter provideBluetoothAdapter(BluetoothManager bluetoothManager) { return bluetoothManager.getAdapter(); } @Provides @Singleton static TextClassificationManager provideTextClassificationManager(Context context) { return context.getSystemService(TextClassificationManager.class); } }
packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package com.android.systemui.clipboardoverlay; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISS_TAPPED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHARE_TAPPED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED; import static com.android.systemui.flags.Flags.CLIPBOARD_REMOTE_BEHAVIOR; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; Loading @@ -29,10 +31,13 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.animation.Animator; import android.app.RemoteAction; import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.net.Uri; import android.os.PersistableBundle; import android.view.textclassifier.TextLinks; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; Loading @@ -42,6 +47,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.screenshot.TimeoutHandler; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; import org.junit.After; import org.junit.Before; Loading @@ -50,7 +57,12 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.util.Optional; @SmallTest @RunWith(AndroidJUnit4.class) Loading Loading @@ -80,6 +92,8 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { private ArgumentCaptor<ClipboardOverlayView.ClipboardOverlayCallbacks> mOverlayCallbacksCaptor; private ClipboardOverlayView.ClipboardOverlayCallbacks mCallbacks; private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); @Before public void setup() { MockitoAnnotations.initMocks(this); Loading @@ -101,6 +115,7 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { mTimeoutHandler, mFeatureFlags, mClipboardUtils, mExecutor, mUiEventLogger); verify(mClipboardOverlayView).setCallbacks(mOverlayCallbacksCaptor.capture()); mCallbacks = mOverlayCallbacksCaptor.getValue(); Loading Loading @@ -237,4 +252,29 @@ public class ClipboardOverlayControllerTest extends SysuiTestCase { verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_DISMISS_TAPPED, 0, "second.package"); verifyNoMoreInteractions(mUiEventLogger); } @Test public void test_logOnClipboardActionsShown() { ClipData.Item item = mSampleClipData.getItemAt(0); item.setTextLinks(Mockito.mock(TextLinks.class)); mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true); when(mClipboardUtils.isRemoteCopy(any(Context.class), any(ClipData.class), anyString())) .thenReturn(true); when(mClipboardUtils.getAction(any(ClipData.Item.class), anyString())) .thenReturn(Optional.of(Mockito.mock(RemoteAction.class))); when(mClipboardOverlayView.post(any(Runnable.class))).thenAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { ((Runnable) invocation.getArgument(0)).run(); return null; } }); mOverlayController.setClipData( new ClipData(mSampleClipData.getDescription(), item), "actionShownSource"); mExecutor.runAllReady(); verify(mUiEventLogger).log(CLIPBOARD_OVERLAY_ACTION_SHOWN, 0, "actionShownSource"); verifyNoMoreInteractions(mUiEventLogger); } }