1 /* 2 * Copyright (C) 2023 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 17 package com.android.systemui.accessibility; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.Mockito.doAnswer; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.when; 26 27 import android.hardware.input.InputManager; 28 import android.os.RemoteException; 29 import android.telecom.TelecomManager; 30 import android.telephony.TelephonyManager; 31 import android.testing.AndroidTestingRunner; 32 import android.testing.TestableLooper; 33 import android.view.KeyEvent; 34 35 import androidx.test.filters.SmallTest; 36 37 import com.android.systemui.SysuiTestCase; 38 import com.android.systemui.recents.Recents; 39 import com.android.systemui.settings.FakeDisplayTracker; 40 import com.android.systemui.settings.UserTracker; 41 import com.android.systemui.shade.ShadeController; 42 import com.android.systemui.shade.ShadeViewController; 43 import com.android.systemui.statusbar.NotificationShadeWindowController; 44 import com.android.systemui.statusbar.phone.CentralSurfaces; 45 46 import dagger.Lazy; 47 48 import org.junit.Before; 49 import org.junit.Test; 50 import org.junit.runner.RunWith; 51 import org.mockito.Mock; 52 import org.mockito.MockitoAnnotations; 53 54 import java.util.ArrayList; 55 import java.util.List; 56 import java.util.Optional; 57 58 @TestableLooper.RunWithLooper 59 @SmallTest 60 @RunWith(AndroidTestingRunner.class) 61 public class SystemActionsTest extends SysuiTestCase { 62 @Mock 63 private UserTracker mUserTracker; 64 @Mock 65 private NotificationShadeWindowController mNotificationShadeController; 66 @Mock 67 private ShadeController mShadeController; 68 @Mock 69 private ShadeViewController mShadeViewController; 70 @Mock 71 private Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy; 72 @Mock 73 private Optional<Recents> mRecentsOptional; 74 @Mock 75 private TelecomManager mTelecomManager; 76 @Mock 77 private InputManager mInputManager; 78 private final FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext); 79 80 private SystemActions mSystemActions; 81 82 @Before setUp()83 public void setUp() throws RemoteException { 84 MockitoAnnotations.initMocks(this); 85 mContext.addMockSystemService(TelecomManager.class, mTelecomManager); 86 mContext.addMockSystemService(InputManager.class, mInputManager); 87 mSystemActions = new SystemActions(mContext, mUserTracker, mNotificationShadeController, 88 mShadeController, () -> mShadeViewController, mCentralSurfacesOptionalLazy, 89 mRecentsOptional, mDisplayTracker); 90 } 91 92 @Test handleHeadsetHook_callStateIdle_injectsKeyEvents()93 public void handleHeadsetHook_callStateIdle_injectsKeyEvents() { 94 when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_IDLE); 95 // Use a custom doAnswer captor that copies the KeyEvent before storing it, because the 96 // method under test modifies the event object after injecting it which prevents 97 // reliably asserting on the event properties. 98 final List<KeyEvent> keyEvents = new ArrayList<>(); 99 doAnswer(invocation -> { 100 keyEvents.add(new KeyEvent(invocation.getArgument(0))); 101 return null; 102 }).when(mInputManager).injectInputEvent(any(), anyInt()); 103 104 mSystemActions.handleHeadsetHook(); 105 106 assertThat(keyEvents.size()).isEqualTo(2); 107 assertThat(keyEvents.get(0).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_HEADSETHOOK); 108 assertThat(keyEvents.get(0).getAction()).isEqualTo(KeyEvent.ACTION_DOWN); 109 assertThat(keyEvents.get(1).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_HEADSETHOOK); 110 assertThat(keyEvents.get(1).getAction()).isEqualTo(KeyEvent.ACTION_UP); 111 } 112 113 @Test handleHeadsetHook_callStateRinging_answersCall()114 public void handleHeadsetHook_callStateRinging_answersCall() { 115 when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_RINGING); 116 117 mSystemActions.handleHeadsetHook(); 118 119 verify(mTelecomManager).acceptRingingCall(); 120 } 121 122 @Test handleHeadsetHook_callStateOffhook_endsCall()123 public void handleHeadsetHook_callStateOffhook_endsCall() { 124 when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_OFFHOOK); 125 126 mSystemActions.handleHeadsetHook(); 127 128 verify(mTelecomManager).endCall(); 129 } 130 } 131