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

Commit 548dd132 authored by Miranda Kephart's avatar Miranda Kephart Committed by Automerger Merge Worker
Browse files

Merge "Just show toast on clipboard change if user not set up" into tm-qpr-dev am: bddf0cef

parents 297bf9e6 bddf0cef
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -16,15 +16,21 @@

package com.android.systemui.clipboardoverlay;

import static android.content.ClipDescription.CLASSIFICATION_COMPLETE;

import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN;

import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
@@ -56,6 +62,7 @@ public class ClipboardListener implements
    private final DeviceConfigProxy mDeviceConfig;
    private final Provider<ClipboardOverlayController> mOverlayProvider;
    private final ClipboardOverlayControllerLegacyFactory mOverlayFactory;
    private final ClipboardToast mClipboardToast;
    private final ClipboardManager mClipboardManager;
    private final UiEventLogger mUiEventLogger;
    private final FeatureFlags mFeatureFlags;
@@ -66,6 +73,7 @@ public class ClipboardListener implements
    public ClipboardListener(Context context, DeviceConfigProxy deviceConfigProxy,
            Provider<ClipboardOverlayController> clipboardOverlayControllerProvider,
            ClipboardOverlayControllerLegacyFactory overlayFactory,
            ClipboardToast clipboardToast,
            ClipboardManager clipboardManager,
            UiEventLogger uiEventLogger,
            FeatureFlags featureFlags) {
@@ -73,6 +81,7 @@ public class ClipboardListener implements
        mDeviceConfig = deviceConfigProxy;
        mOverlayProvider = clipboardOverlayControllerProvider;
        mOverlayFactory = overlayFactory;
        mClipboardToast = clipboardToast;
        mClipboardManager = clipboardManager;
        mUiEventLogger = uiEventLogger;
        mFeatureFlags = featureFlags;
@@ -102,6 +111,15 @@ public class ClipboardListener implements
            return;
        }

        if (!isUserSetupComplete()) {
            // just show a toast, user should not access intents from this state
            if (shouldShowToast(clipData)) {
                mUiEventLogger.log(CLIPBOARD_TOAST_SHOWN, 0, clipSource);
                mClipboardToast.showCopiedToast();
            }
            return;
        }

        boolean enabled = mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR);
        if (mClipboardOverlay == null || enabled != mUsingNewOverlay) {
            mUsingNewOverlay = enabled;
@@ -136,10 +154,26 @@ public class ClipboardListener implements
        return clipData.getDescription().getExtras().getBoolean(EXTRA_SUPPRESS_OVERLAY, false);
    }

    boolean shouldShowToast(ClipData clipData) {
        if (clipData == null) {
            return false;
        } else if (clipData.getDescription().getClassificationStatus() == CLASSIFICATION_COMPLETE) {
            // only show for classification complete if we aren't already showing a toast, to ignore
            // the duplicate ClipData with classification
            return !mClipboardToast.isShowing();
        }
        return true;
    }

    private static boolean isEmulator() {
        return SystemProperties.getBoolean("ro.boot.qemu", false);
    }

    private boolean isUserSetupComplete() {
        return Settings.Secure.getInt(mContext.getContentResolver(),
                SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
    }

    interface ClipboardOverlay {
        void setClipData(ClipData clipData, String clipSource);

+3 −1
Original line number Diff line number Diff line
@@ -43,7 +43,9 @@ public enum ClipboardOverlayEvent implements UiEventLogger.UiEventEnum {
    @UiEvent(doc = "clipboard overlay tapped outside")
    CLIPBOARD_OVERLAY_TAP_OUTSIDE(1077),
    @UiEvent(doc = "clipboard overlay dismissed, miscellaneous reason")
    CLIPBOARD_OVERLAY_DISMISSED_OTHER(1078);
    CLIPBOARD_OVERLAY_DISMISSED_OTHER(1078),
    @UiEvent(doc = "clipboard toast shown")
    CLIPBOARD_TOAST_SHOWN(1270);

    private final int mId;

+56 −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.systemui.clipboardoverlay;

import android.content.Context;
import android.widget.Toast;

import com.android.systemui.R;

import javax.inject.Inject;

/**
 * Utility class for showing a simple clipboard toast on copy.
 */
class ClipboardToast extends Toast.Callback {
    private final Context mContext;
    private Toast mCopiedToast;

    @Inject
    ClipboardToast(Context context) {
        mContext = context;
    }

    void showCopiedToast() {
        if (mCopiedToast != null) {
            mCopiedToast.cancel();
        }
        mCopiedToast = Toast.makeText(mContext,
                R.string.clipboard_overlay_text_copied, Toast.LENGTH_SHORT);
        mCopiedToast.show();
    }

    boolean isShowing() {
        return mCopiedToast != null;
    }

    @Override // Toast.Callback
    public void onToastHidden() {
        super.onToastHidden();
        mCopiedToast = null;
    }
}
+44 −35
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.systemui.clipboardoverlay;

import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;

import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -32,6 +34,7 @@ import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.os.PersistableBundle;
import android.provider.DeviceConfig;
import android.provider.Settings;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -66,6 +69,8 @@ public class ClipboardListenerTest extends SysuiTestCase {
    @Mock
    private ClipboardOverlayController mOverlayController;
    @Mock
    private ClipboardToast mClipboardToast;
    @Mock
    private UiEventLogger mUiEventLogger;
    @Mock
    private FeatureFlags mFeatureFlags;
@@ -84,6 +89,8 @@ public class ClipboardListenerTest extends SysuiTestCase {
    @Spy
    private Provider<ClipboardOverlayController> mOverlayControllerProvider;

    private ClipboardListener mClipboardListener;


    @Before
    public void setup() {
@@ -93,7 +100,8 @@ public class ClipboardListenerTest extends SysuiTestCase {
        when(mClipboardOverlayControllerLegacyFactory.create(any()))
                .thenReturn(mOverlayControllerLegacy);
        when(mClipboardManager.hasPrimaryClip()).thenReturn(true);

        Settings.Secure.putInt(
                mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 1);

        mSampleClipData = new ClipData("Test", new String[]{"text/plain"},
                new ClipData.Item("Test Item"));
@@ -101,16 +109,17 @@ public class ClipboardListenerTest extends SysuiTestCase {
        when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource);

        mDeviceConfigProxy = new DeviceConfigProxyFake();

        mClipboardListener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory,
                mClipboardToast, mClipboardManager, mUiEventLogger, mFeatureFlags);
    }

    @Test
    public void test_disabled() {
        mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
                "false", false);
        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory,
                mClipboardManager, mUiEventLogger, mFeatureFlags);
        listener.start();
        mClipboardListener.start();
        verifyZeroInteractions(mClipboardManager);
        verifyZeroInteractions(mUiEventLogger);
    }
@@ -119,10 +128,7 @@ public class ClipboardListenerTest extends SysuiTestCase {
    public void test_enabled() {
        mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
                "true", false);
        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory,
                mClipboardManager, mUiEventLogger, mFeatureFlags);
        listener.start();
        mClipboardListener.start();
        verify(mClipboardManager).addPrimaryClipChangedListener(any());
        verifyZeroInteractions(mUiEventLogger);
    }
@@ -133,11 +139,8 @@ public class ClipboardListenerTest extends SysuiTestCase {

        mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
                "true", false);
        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory,
                mClipboardManager, mUiEventLogger, mFeatureFlags);
        listener.start();
        listener.onPrimaryClipChanged();
        mClipboardListener.start();
        mClipboardListener.onPrimaryClipChanged();

        verify(mClipboardOverlayControllerLegacyFactory).create(any());

@@ -152,14 +155,14 @@ public class ClipboardListenerTest extends SysuiTestCase {
        // Should clear the overlay controller
        mRunnableCaptor.getValue().run();

        listener.onPrimaryClipChanged();
        mClipboardListener.onPrimaryClipChanged();

        verify(mClipboardOverlayControllerLegacyFactory, times(2)).create(any());

        // Not calling the runnable here, just change the clip again and verify that the overlay is
        // NOT recreated.

        listener.onPrimaryClipChanged();
        mClipboardListener.onPrimaryClipChanged();

        verify(mClipboardOverlayControllerLegacyFactory, times(2)).create(any());
        verifyZeroInteractions(mOverlayControllerProvider);
@@ -171,11 +174,8 @@ public class ClipboardListenerTest extends SysuiTestCase {

        mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
                "true", false);
        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory,
                mClipboardManager, mUiEventLogger, mFeatureFlags);
        listener.start();
        listener.onPrimaryClipChanged();
        mClipboardListener.start();
        mClipboardListener.onPrimaryClipChanged();

        verify(mOverlayControllerProvider).get();

@@ -190,14 +190,14 @@ public class ClipboardListenerTest extends SysuiTestCase {
        // Should clear the overlay controller
        mRunnableCaptor.getValue().run();

        listener.onPrimaryClipChanged();
        mClipboardListener.onPrimaryClipChanged();

        verify(mOverlayControllerProvider, times(2)).get();

        // Not calling the runnable here, just change the clip again and verify that the overlay is
        // NOT recreated.

        listener.onPrimaryClipChanged();
        mClipboardListener.onPrimaryClipChanged();

        verify(mOverlayControllerProvider, times(2)).get();
        verifyZeroInteractions(mClipboardOverlayControllerLegacyFactory);
@@ -233,13 +233,10 @@ public class ClipboardListenerTest extends SysuiTestCase {
    public void test_logging_enterAndReenter() {
        when(mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR)).thenReturn(false);

        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory,
                mClipboardManager, mUiEventLogger, mFeatureFlags);
        listener.start();
        mClipboardListener.start();

        listener.onPrimaryClipChanged();
        listener.onPrimaryClipChanged();
        mClipboardListener.onPrimaryClipChanged();
        mClipboardListener.onPrimaryClipChanged();

        verify(mUiEventLogger, times(1)).log(
                ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED, 0, mSampleSource);
@@ -251,17 +248,29 @@ public class ClipboardListenerTest extends SysuiTestCase {
    public void test_logging_enterAndReenter_new() {
        when(mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR)).thenReturn(true);

        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory,
                mClipboardManager, mUiEventLogger, mFeatureFlags);
        listener.start();
        mClipboardListener.start();

        listener.onPrimaryClipChanged();
        listener.onPrimaryClipChanged();
        mClipboardListener.onPrimaryClipChanged();
        mClipboardListener.onPrimaryClipChanged();

        verify(mUiEventLogger, times(1)).log(
                ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED, 0, mSampleSource);
        verify(mUiEventLogger, times(1)).log(
                ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED, 0, mSampleSource);
    }

    @Test
    public void test_userSetupIncomplete_showsToast() {
        Settings.Secure.putInt(
                mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0);

        mClipboardListener.start();
        mClipboardListener.onPrimaryClipChanged();

        verify(mUiEventLogger, times(1)).log(
                ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN, 0, mSampleSource);
        verify(mClipboardToast, times(1)).showCopiedToast();
        verifyZeroInteractions(mOverlayControllerProvider);
        verifyZeroInteractions(mClipboardOverlayControllerLegacyFactory);
    }
}