• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server.telecom.tests;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.mockito.ArgumentMatchers.anyInt;
21 import static org.mockito.Mockito.eq;
22 import static org.mockito.Mockito.never;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.when;
26 
27 import android.content.Intent;
28 import android.media.session.MediaSession;
29 import android.view.KeyEvent;
30 
31 import androidx.test.filters.MediumTest;
32 import androidx.test.filters.SmallTest;
33 
34 import com.android.server.telecom.Call;
35 import com.android.server.telecom.CallsManager;
36 import com.android.server.telecom.HeadsetMediaButton;
37 import com.android.server.telecom.HeadsetMediaButton.MediaSessionWrapper;
38 import com.android.server.telecom.TelecomSystem;
39 
40 import org.junit.After;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.junit.runners.JUnit4;
45 import org.mockito.ArgumentCaptor;
46 import org.mockito.Mock;
47 import org.mockito.Mockito;
48 
49 @RunWith(JUnit4.class)
50 public class HeadsetMediaButtonTest extends TelecomTestCase {
51     private static final int TEST_TIMEOUT_MILLIS = 1000;
52 
53     private HeadsetMediaButton mHeadsetMediaButton;
54     private MediaSession.Callback mSessionCallback;
55 
56     @Mock private CallsManager mMockCallsManager;
57     @Mock private HeadsetMediaButton.MediaSessionAdapter mMediaSessionAdapter;
58     private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {};
59 
60     @Override
61     @Before
setUp()62     public void setUp() throws Exception {
63         super.setUp();
64 
65         ArgumentCaptor<MediaSession.Callback> sessionCallbackArgument =
66                 ArgumentCaptor.forClass(MediaSession.Callback.class);
67 
68         mHeadsetMediaButton = new HeadsetMediaButton(mContext, mMockCallsManager, mLock,
69                 mMediaSessionAdapter);
70 
71         verify(mMediaSessionAdapter).setCallback(sessionCallbackArgument.capture());
72         mSessionCallback = sessionCallbackArgument.getValue();
73     }
74 
75     @Override
76     @After
tearDown()77     public void tearDown() throws Exception {
78         mHeadsetMediaButton = null;
79         super.tearDown();
80     }
81 
82     /**
83      * Nominal case; just add a call and remove it.
84      */
85     @SmallTest
86     @Test
testAddCall()87     public void testAddCall() {
88         Call regularCall = getRegularCall();
89 
90         when(mMockCallsManager.hasAnyCalls()).thenReturn(true);
91         mHeadsetMediaButton.onCallAdded(regularCall);
92         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
93         verify(mMediaSessionAdapter).setActive(eq(true));
94         // ... and thus we see how the original code isn't amenable to tests.
95         when(mMediaSessionAdapter.isActive()).thenReturn(true);
96 
97         when(mMockCallsManager.hasAnyCalls()).thenReturn(false);
98         mHeadsetMediaButton.onCallRemoved(regularCall);
99         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
100         verify(mMediaSessionAdapter).setActive(eq(false));
101     }
102 
103     /**
104      * Test a case where a regular call becomes an external call, and back again.
105      */
106     @SmallTest
107     @Test
testRegularCallThatBecomesExternal()108     public void testRegularCallThatBecomesExternal() {
109         Call regularCall = getRegularCall();
110 
111         // Start with a regular old call.
112         when(mMockCallsManager.hasAnyCalls()).thenReturn(true);
113         mHeadsetMediaButton.onCallAdded(regularCall);
114         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
115         verify(mMediaSessionAdapter).setActive(eq(true));
116         when(mMediaSessionAdapter.isActive()).thenReturn(true);
117 
118         // Change so it is external.
119         when(regularCall.isExternalCall()).thenReturn(true);
120         when(mMockCallsManager.hasAnyCalls()).thenReturn(false);
121         mHeadsetMediaButton.onExternalCallChanged(regularCall, true);
122         // Expect to set session inactive.
123         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
124         verify(mMediaSessionAdapter).setActive(eq(false));
125 
126         // For good measure lets make it non-external again.
127         when(regularCall.isExternalCall()).thenReturn(false);
128         when(mMockCallsManager.hasAnyCalls()).thenReturn(true);
129         mHeadsetMediaButton.onExternalCallChanged(regularCall, false);
130         // Expect to set session active.
131         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
132         verify(mMediaSessionAdapter).setActive(eq(true));
133     }
134 
135     @MediumTest
136     @Test
testExternalCallNotChangesState()137     public void testExternalCallNotChangesState() {
138         Call externalCall = getRegularCall();
139         when(externalCall.isExternalCall()).thenReturn(true);
140 
141         mHeadsetMediaButton.onCallAdded(externalCall);
142         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
143         verify(mMediaSessionAdapter, never()).setActive(eq(true));
144 
145         mHeadsetMediaButton.onCallRemoved(externalCall);
146         waitForHandlerAction(mHeadsetMediaButton.getHandler(), TEST_TIMEOUT_MILLIS);
147         verify(mMediaSessionAdapter, never()).setActive(eq(false));
148     }
149 
150     @SmallTest
151     @Test
testCallbackReceivesKeyEventUnaware()152     public void testCallbackReceivesKeyEventUnaware() {
153         mSessionCallback.onMediaButtonEvent(getKeyEventIntent(
154                 KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0, false));
155         verify(mMockCallsManager, never()).onMediaButton(anyInt());
156     }
157 
158     @SmallTest
159     @Test
testCallbackReceivesKeyEventShortClick()160     public void testCallbackReceivesKeyEventShortClick() {
161         mSessionCallback.onMediaButtonEvent(getKeyEventIntent(
162                 KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK, false));
163         verify(mMockCallsManager, never()).onMediaButton(anyInt());
164 
165         mSessionCallback.onMediaButtonEvent(getKeyEventIntent(
166                 KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK, false));
167         verify(mMockCallsManager, times(1)).onMediaButton(HeadsetMediaButton.SHORT_PRESS);
168     }
169 
170     @SmallTest
171     @Test
testCallbackReceivesKeyEventLongClick()172     public void testCallbackReceivesKeyEventLongClick() {
173         mSessionCallback.onMediaButtonEvent(getKeyEventIntent(
174                 KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK, true));
175         verify(mMockCallsManager, times(1)).onMediaButton(HeadsetMediaButton.LONG_PRESS);
176 
177         mSessionCallback.onMediaButtonEvent(getKeyEventIntent(
178                 KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK, false));
179         verify(mMockCallsManager, times(1)).onMediaButton(HeadsetMediaButton.LONG_PRESS);
180     }
181 
182     @SmallTest
183     @Test
testMediaSessionWrapperSetActive()184     public void testMediaSessionWrapperSetActive() {
185         MediaSession session = Mockito.mock(MediaSession.class);
186         MediaSessionWrapper wrapper = mHeadsetMediaButton.new MediaSessionWrapper(session);
187 
188         final boolean active = true;
189         wrapper.setActive(active);
190         verify(session).setActive(active);
191     }
192 
193     @SmallTest
194     @Test
testMediaSessionWrapperSetCallback()195     public void testMediaSessionWrapperSetCallback() {
196         MediaSession session = Mockito.mock(MediaSession.class);
197         MediaSessionWrapper wrapper = mHeadsetMediaButton.new MediaSessionWrapper(session);
198 
199         wrapper.setCallback(mSessionCallback);
200         verify(session).setCallback(mSessionCallback);
201     }
202 
203     @SmallTest
204     @Test
testMediaSessionWrapperIsActive()205     public void testMediaSessionWrapperIsActive() {
206         MediaSession session = Mockito.mock(MediaSession.class);
207         MediaSessionWrapper wrapper = mHeadsetMediaButton.new MediaSessionWrapper(session);
208 
209         final boolean active = true;
210         when(session.isActive()).thenReturn(active);
211         assertEquals(active, wrapper.isActive());
212     }
213 
214     /**
215      * @return a mock call instance of a regular non-external call.
216      */
getRegularCall()217     private Call getRegularCall() {
218         Call regularCall = Mockito.mock(Call.class);
219         when(regularCall.isExternalCall()).thenReturn(false);
220         return regularCall;
221     }
222 
getKeyEventIntent(int action, int code, boolean longPress)223     private Intent getKeyEventIntent(int action, int code, boolean longPress) {
224         KeyEvent e = new KeyEvent(action, code);
225         if (longPress) {
226             e = KeyEvent.changeFlags(e, KeyEvent.FLAG_LONG_PRESS);
227         }
228 
229         Intent intent = new Intent();
230         intent.putExtra(Intent.EXTRA_KEY_EVENT, e);
231         return intent;
232     }
233 }
234