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

Commit 51fd0c68 authored by Matt Casey's avatar Matt Casey Committed by Android (Google) Code Review
Browse files

Merge "Tests for ClipboardListener"

parents a52e963d c877c29a
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -18,15 +18,13 @@ package com.android.systemui.clipboardoverlay;

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

import static java.util.Objects.requireNonNull;

import android.content.ClipboardManager;
import android.content.Context;
import android.provider.DeviceConfig;

import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.screenshot.TimeoutHandler;
import com.android.systemui.util.DeviceConfigProxy;

import javax.inject.Inject;

@@ -37,19 +35,24 @@ import javax.inject.Inject;
public class ClipboardListener extends CoreStartable
        implements ClipboardManager.OnPrimaryClipChangedListener {

    private final DeviceConfigProxy mDeviceConfig;
    private final ClipboardOverlayControllerFactory mOverlayFactory;
    private final ClipboardManager mClipboardManager;
    private ClipboardOverlayController mClipboardOverlayController;
    private ClipboardManager mClipboardManager;

    @Inject
    public ClipboardListener(Context context) {
    public ClipboardListener(Context context, DeviceConfigProxy deviceConfigProxy,
            ClipboardOverlayControllerFactory overlayFactory, ClipboardManager clipboardManager) {
        super(context);
        mDeviceConfig = deviceConfigProxy;
        mOverlayFactory = overlayFactory;
        mClipboardManager = clipboardManager;
    }

    @Override
    public void start() {
        if (DeviceConfig.getBoolean(
        if (mDeviceConfig.getBoolean(
                DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED, true)) {
            mClipboardManager = requireNonNull(mContext.getSystemService(ClipboardManager.class));
            mClipboardManager.addPrimaryClipChangedListener(this);
        }
    }
@@ -60,8 +63,7 @@ public class ClipboardListener extends CoreStartable
            return;
        }
        if (mClipboardOverlayController == null) {
            mClipboardOverlayController =
                    new ClipboardOverlayController(mContext, new TimeoutHandler(mContext));
            mClipboardOverlayController = mOverlayFactory.create(mContext);
        }
        mClipboardOverlayController.setClipData(
                mClipboardManager.getPrimaryClip(), mClipboardManager.getPrimaryClipSource());
+41 −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 com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.screenshot.TimeoutHandler;

import javax.inject.Inject;

/**
 * A factory that churns out ClipboardOverlayControllers on demand.
 */
@SysUISingleton
public class ClipboardOverlayControllerFactory {

    @Inject
    public ClipboardOverlayControllerFactory() {}

    /**
     * One new ClipboardOverlayController, coming right up!
     */
    public ClipboardOverlayController create(Context context) {
        return new ClipboardOverlayController(context, new TimeoutHandler(context));
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import com.android.systemui.accessibility.ModeSwitchesController;
import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger;
import com.android.systemui.clipboardoverlay.ClipboardOverlayControllerFactory;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
@@ -291,4 +292,11 @@ public class DependencyProvider {
    public ModeSwitchesController providesModeSwitchesController(Context context) {
        return new ModeSwitchesController(context);
    }

    /***/
    @Provides
    @SysUISingleton
    public ClipboardOverlayControllerFactory provideClipboardOverlayControllerFactory() {
        return new ClipboardOverlayControllerFactory();
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.app.admin.DevicePolicyManager;
import android.app.role.RoleManager;
import android.app.smartspace.SmartspaceManager;
import android.app.trust.TrustManager;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.om.OverlayManager;
@@ -449,6 +450,12 @@ public class FrameworkServicesModule {
        return pm;
    }

    @Provides
    @Singleton
    static ClipboardManager provideClipboardManager(Context context) {
        return context.getSystemService(ClipboardManager.class);
    }

    @Provides
    @Singleton
    static SmartspaceManager provideSmartspaceManager(Context context) {
+137 −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 static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.provider.DeviceConfig;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.DeviceConfigProxyFake;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class ClipboardListenerTest extends SysuiTestCase {

    @Mock
    private ClipboardManager mClipboardManager;
    @Mock
    private ClipboardOverlayControllerFactory mClipboardOverlayControllerFactory;
    @Mock
    private ClipboardOverlayController mOverlayController;
    private DeviceConfigProxyFake mDeviceConfigProxy;

    private ClipData mSampleClipData;
    private String mSampleSource = "Example source";

    @Captor
    private ArgumentCaptor<Runnable> mRunnableCaptor;
    @Captor
    private ArgumentCaptor<ClipData> mClipDataCaptor;
    @Captor
    private ArgumentCaptor<String> mStringCaptor;


    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        when(mClipboardOverlayControllerFactory.create(any())).thenReturn(
                mOverlayController);
        when(mClipboardManager.hasPrimaryClip()).thenReturn(true);


        mSampleClipData = new ClipData("Test", new String[]{"text/plain"},
                new ClipData.Item("Test Item"));
        when(mClipboardManager.getPrimaryClip()).thenReturn(mSampleClipData);
        when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource);

        mDeviceConfigProxy = new DeviceConfigProxyFake();
    }

    @Test
    public void test_disabled() {
        mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
                "false", false);
        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mClipboardOverlayControllerFactory, mClipboardManager);
        listener.start();
        verifyZeroInteractions(mClipboardManager);
    }

    @Test
    public void test_enabled() {
        mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
                "true", false);
        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mClipboardOverlayControllerFactory, mClipboardManager);
        listener.start();
        verify(mClipboardManager).addPrimaryClipChangedListener(any());
    }

    @Test
    public void test_consecutiveCopies() {
        mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
                "true", false);
        ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
                mClipboardOverlayControllerFactory, mClipboardManager);
        listener.start();
        listener.onPrimaryClipChanged();

        verify(mClipboardOverlayControllerFactory).create(any());

        verify(mOverlayController).setClipData(mClipDataCaptor.capture(), mStringCaptor.capture());

        assertEquals(mSampleClipData, mClipDataCaptor.getValue());
        assertEquals(mSampleSource, mStringCaptor.getValue());

        verify(mOverlayController).setOnSessionCompleteListener(mRunnableCaptor.capture());

        // Should clear the overlay controller
        mRunnableCaptor.getValue().run();

        listener.onPrimaryClipChanged();

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

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

        listener.onPrimaryClipChanged();

        verify(mClipboardOverlayControllerFactory, times(2)).create(any());
    }
}