Home | History | Annotate | Download | only in a2dpsink
      1 /*
      2  * Copyright (C) 2017 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.bluetooth.a2dpsink;
     18 
     19 import static org.mockito.Mockito.*;
     20 
     21 import android.content.Context;
     22 import android.content.pm.PackageManager;
     23 import android.content.res.Resources;
     24 import android.media.AudioManager;
     25 import android.os.HandlerThread;
     26 import android.os.Looper;
     27 import android.support.test.InstrumentationRegistry;
     28 import android.support.test.filters.MediumTest;
     29 import android.support.test.runner.AndroidJUnit4;
     30 
     31 import com.android.bluetooth.R;
     32 
     33 import org.junit.Assume;
     34 import org.junit.Before;
     35 import org.junit.Test;
     36 import org.junit.runner.RunWith;
     37 import org.mockito.Mock;
     38 import org.mockito.MockitoAnnotations;
     39 
     40 @MediumTest
     41 @RunWith(AndroidJUnit4.class)
     42 public class A2dpSinkStreamHandlerTest {
     43     private static final int DUCK_PERCENT = 75;
     44     private HandlerThread mHandlerThread;
     45     private A2dpSinkStreamHandler mStreamHandler;
     46     private Context mTargetContext;
     47 
     48     @Mock private Context mMockContext;
     49 
     50     @Mock private A2dpSinkStateMachine mMockA2dpSink;
     51 
     52     @Mock private AudioManager mMockAudioManager;
     53 
     54     @Mock private Resources mMockResources;
     55 
     56     @Mock private PackageManager mMockPackageManager;
     57 
     58     @Before
     59     public void setUp() {
     60         mTargetContext = InstrumentationRegistry.getTargetContext();
     61         Assume.assumeTrue("Ignore test when A2dpSinkService is not enabled",
     62                 mTargetContext.getResources().getBoolean(R.bool.profile_supported_a2dp_sink));
     63         MockitoAnnotations.initMocks(this);
     64         // Mock the looper
     65         if (Looper.myLooper() == null) {
     66             Looper.prepare();
     67         }
     68 
     69         mHandlerThread = new HandlerThread("A2dpSinkStreamHandlerTest");
     70         mHandlerThread.start();
     71 
     72         when(mMockContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mMockAudioManager);
     73         when(mMockContext.getResources()).thenReturn(mMockResources);
     74         when(mMockResources.getInteger(anyInt())).thenReturn(DUCK_PERCENT);
     75         when(mMockAudioManager.requestAudioFocus(any())).thenReturn(
     76                 AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
     77         when(mMockAudioManager.abandonAudioFocus(any())).thenReturn(AudioManager.AUDIOFOCUS_GAIN);
     78         doNothing().when(mMockA2dpSink).informAudioTrackGainNative(anyFloat());
     79         when(mMockContext.getMainLooper()).thenReturn(mHandlerThread.getLooper());
     80         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
     81         when(mMockPackageManager.hasSystemFeature(any())).thenReturn(false);
     82 
     83         mStreamHandler = spy(new A2dpSinkStreamHandler(mMockA2dpSink, mMockContext));
     84     }
     85 
     86     @Test
     87     public void testSrcStart() {
     88         // Stream started without local play, expect no change in streaming.
     89         mStreamHandler.handleMessage(
     90                 mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_STR_START));
     91         verify(mMockAudioManager, times(0)).requestAudioFocus(any());
     92         verify(mMockA2dpSink, times(0)).informAudioFocusStateNative(1);
     93         verify(mMockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
     94     }
     95 
     96     @Test
     97     public void testSrcStop() {
     98         // Stream stopped without local play, expect no change in streaming.
     99         mStreamHandler.handleMessage(
    100                 mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_STR_STOP));
    101         verify(mMockAudioManager, times(0)).requestAudioFocus(any());
    102         verify(mMockA2dpSink, times(0)).informAudioFocusStateNative(1);
    103         verify(mMockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
    104     }
    105 
    106     @Test
    107     public void testSnkPlay() {
    108         // Play was pressed locally, expect streaming to start.
    109         mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SNK_PLAY));
    110         verify(mMockAudioManager, times(1)).requestAudioFocus(any());
    111         verify(mMockA2dpSink, times(1)).informAudioFocusStateNative(1);
    112         verify(mMockA2dpSink, times(1)).informAudioTrackGainNative(1.0f);
    113     }
    114 
    115     @Test
    116     public void testSnkPause() {
    117         // Pause was pressed locally, expect streaming to stop.
    118         mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SNK_PAUSE));
    119         verify(mMockAudioManager, times(0)).requestAudioFocus(any());
    120         verify(mMockA2dpSink, times(0)).informAudioFocusStateNative(1);
    121         verify(mMockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
    122     }
    123 
    124     @Test
    125     public void testDisconnect() {
    126         // Remote device was disconnected, expect streaming to stop.
    127         testSnkPlay();
    128         mStreamHandler.handleMessage(
    129                 mStreamHandler.obtainMessage(A2dpSinkStreamHandler.DISCONNECT));
    130         verify(mMockAudioManager, times(0)).abandonAudioFocus(any());
    131         verify(mMockA2dpSink, times(0)).informAudioFocusStateNative(0);
    132     }
    133 
    134     @Test
    135     public void testSrcPlay() {
    136         // Play was pressed remotely, expect no streaming due to lack of audio focus.
    137         mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_PLAY));
    138         verify(mMockAudioManager, times(0)).requestAudioFocus(any());
    139         verify(mMockA2dpSink, times(0)).informAudioFocusStateNative(1);
    140         verify(mMockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
    141     }
    142 
    143     @Test
    144     public void testSrcPlayIot() {
    145         // Play was pressed remotely for an iot device, expect streaming to start.
    146         when(mMockPackageManager.hasSystemFeature(any())).thenReturn(true);
    147         mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_PLAY));
    148         verify(mMockAudioManager, times(1)).requestAudioFocus(any());
    149         verify(mMockA2dpSink, times(1)).informAudioFocusStateNative(1);
    150         verify(mMockA2dpSink, times(1)).informAudioTrackGainNative(1.0f);
    151     }
    152 
    153     @Test
    154     public void testSrcPause() {
    155         // Play was pressed locally, expect streaming to start.
    156         mStreamHandler.handleMessage(mStreamHandler.obtainMessage(A2dpSinkStreamHandler.SRC_PLAY));
    157         verify(mMockAudioManager, times(0)).requestAudioFocus(any());
    158         verify(mMockA2dpSink, times(0)).informAudioFocusStateNative(1);
    159         verify(mMockA2dpSink, times(0)).informAudioTrackGainNative(1.0f);
    160     }
    161 
    162     @Test
    163     public void testFocusGain() {
    164         // Focus was gained, expect streaming to resume.
    165         testSnkPlay();
    166         mStreamHandler.handleMessage(
    167                 mStreamHandler.obtainMessage(A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE,
    168                         AudioManager.AUDIOFOCUS_GAIN));
    169         verify(mMockAudioManager, times(1)).requestAudioFocus(any());
    170         verify(mMockA2dpSink, times(2)).informAudioFocusStateNative(1);
    171         verify(mMockA2dpSink, times(2)).informAudioTrackGainNative(1.0f);
    172     }
    173 
    174     @Test
    175     public void testFocusTransientMayDuck() {
    176         // TransientMayDuck focus was gained, expect audio stream to duck.
    177         testSnkPlay();
    178         mStreamHandler.handleMessage(
    179                 mStreamHandler.obtainMessage(A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE,
    180                         AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK));
    181         verify(mMockA2dpSink, times(1)).informAudioTrackGainNative(DUCK_PERCENT / 100.0f);
    182     }
    183 
    184     @Test
    185     public void testFocusLostTransient() {
    186         // Focus was lost transiently, expect streaming to stop.
    187         testSnkPlay();
    188         mStreamHandler.handleMessage(
    189                 mStreamHandler.obtainMessage(A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE,
    190                         AudioManager.AUDIOFOCUS_LOSS_TRANSIENT));
    191         verify(mMockAudioManager, times(0)).abandonAudioFocus(any());
    192         verify(mMockA2dpSink, times(1)).informAudioFocusStateNative(0);
    193     }
    194 
    195     @Test
    196     public void testFocusLost() {
    197         // Focus was lost permanently, expect streaming to stop.
    198         testSnkPlay();
    199         mStreamHandler.handleMessage(
    200                 mStreamHandler.obtainMessage(A2dpSinkStreamHandler.AUDIO_FOCUS_CHANGE,
    201                         AudioManager.AUDIOFOCUS_LOSS));
    202         verify(mMockAudioManager, times(1)).abandonAudioFocus(any());
    203         verify(mMockA2dpSink, times(1)).informAudioFocusStateNative(0);
    204     }
    205 }
    206