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

Commit c877c29a authored by Matt Casey's avatar Matt Casey Committed by Miranda Kephart
Browse files

Tests for ClipboardListener

Had to refactor a bit to make things more injectable.

Test: atest ClipboardListenerTest
Bug: 201090289
Change-Id: If1938272da349bcb374eb9893f785bbf993a7ffd
parent f240e0b7
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());
    }
}