1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.systemui.complication; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.mockito.ArgumentMatchers.any; 20 import static org.mockito.ArgumentMatchers.eq; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.never; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import android.app.smartspace.SmartspaceTarget; 27 import android.testing.AndroidTestingRunner; 28 import android.view.View; 29 30 import androidx.test.filters.SmallTest; 31 32 import com.android.systemui.SysuiTestCase; 33 import com.android.systemui.condition.SelfExecutingMonitor; 34 import com.android.systemui.dreams.DreamOverlayStateController; 35 import com.android.systemui.dreams.smartspace.DreamSmartspaceController; 36 import com.android.systemui.flags.FeatureFlags; 37 import com.android.systemui.flags.Flags; 38 import com.android.systemui.plugins.BcSmartspaceDataPlugin; 39 import com.android.systemui.shared.condition.Condition; 40 import com.android.systemui.shared.condition.Monitor; 41 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.ArgumentCaptor; 46 import org.mockito.Mock; 47 import org.mockito.Mockito; 48 import org.mockito.MockitoAnnotations; 49 50 import java.util.Collections; 51 import java.util.HashSet; 52 import java.util.Set; 53 54 @SmallTest 55 @RunWith(AndroidTestingRunner.class) 56 public class SmartSpaceComplicationTest extends SysuiTestCase { 57 58 @Mock 59 private DreamSmartspaceController mSmartspaceController; 60 61 @Mock 62 private DreamOverlayStateController mDreamOverlayStateController; 63 64 @Mock 65 private SmartSpaceComplication mComplication; 66 67 @Mock 68 private View mBcSmartspaceView; 69 70 @Mock 71 private FeatureFlags mFeatureFlags; 72 73 private Monitor mMonitor; 74 75 private final Set<Condition> mPreconditions = new HashSet<>(); 76 77 @Before setup()78 public void setup() { 79 MockitoAnnotations.initMocks(this); 80 mMonitor = SelfExecutingMonitor.createInstance(); 81 82 when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(false); 83 } 84 85 /** 86 * Ensures {@link SmartSpaceComplication} isn't registered right away on start. 87 */ 88 @Test testRegistrantStart_doesNotAddComplication()89 public void testRegistrantStart_doesNotAddComplication() { 90 final SmartSpaceComplication.Registrant registrant = getRegistrant(); 91 registrant.start(); 92 verify(mDreamOverlayStateController, never()).addComplication(eq(mComplication)); 93 } 94 95 @Test testRegistrantStart_featureEnabled_addOverlayStateCallback()96 public void testRegistrantStart_featureEnabled_addOverlayStateCallback() { 97 final SmartSpaceComplication.Registrant registrant = getRegistrant(); 98 registrant.start(); 99 100 verify(mDreamOverlayStateController).addCallback(any()); 101 } 102 103 @Test testRegistrantStart_featureDisabled_doesNotAddOverlayStateCallback()104 public void testRegistrantStart_featureDisabled_doesNotAddOverlayStateCallback() { 105 when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(true); 106 107 final SmartSpaceComplication.Registrant registrant = getRegistrant(); 108 registrant.start(); 109 110 verify(mDreamOverlayStateController, never()).addCallback(any()); 111 } 112 113 @Test testOverlayActive_addsTargetListener()114 public void testOverlayActive_addsTargetListener() { 115 final SmartSpaceComplication.Registrant registrant = getRegistrant(); 116 registrant.start(); 117 118 final ArgumentCaptor<DreamOverlayStateController.Callback> dreamCallbackCaptor = 119 ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class); 120 verify(mDreamOverlayStateController).addCallback(dreamCallbackCaptor.capture()); 121 122 when(mDreamOverlayStateController.isOverlayActive()).thenReturn(true); 123 dreamCallbackCaptor.getValue().onStateChanged(); 124 125 // Test 126 final ArgumentCaptor<BcSmartspaceDataPlugin.SmartspaceTargetListener> listenerCaptor = 127 ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class); 128 verify(mSmartspaceController).addListener(listenerCaptor.capture()); 129 } 130 131 @Test testOverlayActive_targetsNonEmpty_addsComplication()132 public void testOverlayActive_targetsNonEmpty_addsComplication() { 133 final SmartSpaceComplication.Registrant registrant = getRegistrant(); 134 registrant.start(); 135 136 final ArgumentCaptor<DreamOverlayStateController.Callback> dreamCallbackCaptor = 137 ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class); 138 verify(mDreamOverlayStateController).addCallback(dreamCallbackCaptor.capture()); 139 140 when(mDreamOverlayStateController.isOverlayActive()).thenReturn(true); 141 dreamCallbackCaptor.getValue().onStateChanged(); 142 143 final ArgumentCaptor<BcSmartspaceDataPlugin.SmartspaceTargetListener> listenerCaptor = 144 ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class); 145 verify(mSmartspaceController).addListener(listenerCaptor.capture()); 146 147 // Test 148 final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class); 149 listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.singletonList(target)); 150 verify(mDreamOverlayStateController).addComplication(eq(mComplication)); 151 } 152 153 @Test testOverlayActive_targetsEmpty_addsComplication()154 public void testOverlayActive_targetsEmpty_addsComplication() { 155 final SmartSpaceComplication.Registrant registrant = getRegistrant(); 156 registrant.start(); 157 158 final ArgumentCaptor<DreamOverlayStateController.Callback> dreamCallbackCaptor = 159 ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class); 160 verify(mDreamOverlayStateController).addCallback(dreamCallbackCaptor.capture()); 161 162 when(mDreamOverlayStateController.isOverlayActive()).thenReturn(true); 163 dreamCallbackCaptor.getValue().onStateChanged(); 164 165 final ArgumentCaptor<BcSmartspaceDataPlugin.SmartspaceTargetListener> listenerCaptor = 166 ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class); 167 verify(mSmartspaceController).addListener(listenerCaptor.capture()); 168 169 // Test 170 listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.emptyList()); 171 verify(mDreamOverlayStateController).addComplication(eq(mComplication)); 172 } 173 174 @Test testOverlayInActive_removesTargetListener_removesComplication()175 public void testOverlayInActive_removesTargetListener_removesComplication() { 176 final SmartSpaceComplication.Registrant registrant = getRegistrant(); 177 registrant.start(); 178 179 final ArgumentCaptor<DreamOverlayStateController.Callback> dreamCallbackCaptor = 180 ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class); 181 verify(mDreamOverlayStateController).addCallback(dreamCallbackCaptor.capture()); 182 183 when(mDreamOverlayStateController.isOverlayActive()).thenReturn(true); 184 dreamCallbackCaptor.getValue().onStateChanged(); 185 186 final ArgumentCaptor<BcSmartspaceDataPlugin.SmartspaceTargetListener> listenerCaptor = 187 ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class); 188 verify(mSmartspaceController).addListener(listenerCaptor.capture()); 189 190 listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.emptyList()); 191 verify(mDreamOverlayStateController).addComplication(eq(mComplication)); 192 193 // Test 194 when(mDreamOverlayStateController.isOverlayActive()).thenReturn(false); 195 dreamCallbackCaptor.getValue().onStateChanged(); 196 verify(mSmartspaceController).removeListener(listenerCaptor.getValue()); 197 verify(mDreamOverlayStateController).removeComplication(eq(mComplication)); 198 } 199 200 @Test testGetView_reusesSameView()201 public void testGetView_reusesSameView() { 202 final Complication.ViewHolder viewHolder = 203 new SmartSpaceComplication.SmartSpaceComplicationViewHolder(getContext(), 204 mSmartspaceController, mock(ComplicationLayoutParams.class)); 205 when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mBcSmartspaceView); 206 assertEquals(viewHolder.getView(), viewHolder.getView()); 207 } 208 getRegistrant()209 private SmartSpaceComplication.Registrant getRegistrant() { 210 return new SmartSpaceComplication.Registrant( 211 mDreamOverlayStateController, 212 mComplication, 213 mSmartspaceController, 214 mMonitor, 215 mFeatureFlags); 216 } 217 } 218