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

Commit 10b8cca0 authored by Brad Ebinger's avatar Brad Ebinger Committed by Android (Google) Code Review
Browse files

Merge "Removes the use_stream_voice_call_tones flag" into main

parents de8e9246 b3e3edaa
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -45,17 +45,6 @@ flag {
    }
}

# OWNER=breadley TARGET=24Q4
flag {
  name: "use_stream_voice_call_tones"
  namespace: "telecom"
  description: "Use STREAM_VOICE_CALL only for ToneGenerator"
  bug: "363262590"
  metadata {
      purpose: PURPOSE_BUGFIX
    }
}

# OWNER=breadley TARGET=25Q2
flag {
  name: "enable_respond_via_sms_manager_async"
+0 −129
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.server.telecom;

import com.android.server.telecom.bluetooth.BluetoothRouteManager;

/**
 * A class that acts as a listener to things that could change call audio routing, namely
 * bluetooth status, wired headset status, and dock status.
 */
public class CallAudioRoutePeripheralAdapter implements WiredHeadsetManager.Listener,
        DockManager.Listener, BluetoothRouteManager.BluetoothStateListener {

    private final CallAudioRouteAdapter mCallAudioAdapter;
    private final BluetoothRouteManager mBluetoothRouteManager;
    private final AsyncRingtonePlayer mRingtonePlayer;

    public CallAudioRoutePeripheralAdapter(
            CallAudioRouteAdapter callAudioRouteAdapter,
            BluetoothRouteManager bluetoothManager,
            WiredHeadsetManager wiredHeadsetManager,
            DockManager dockManager,
            AsyncRingtonePlayer ringtonePlayer) {
        mCallAudioAdapter = callAudioRouteAdapter;
        mBluetoothRouteManager = bluetoothManager;
        mRingtonePlayer = ringtonePlayer;

        mBluetoothRouteManager.setListener(this);
        wiredHeadsetManager.addListener(this);
        dockManager.addListener(this);
    }

    public boolean isBluetoothAudioOn() {
        return mBluetoothRouteManager.isBluetoothAudioConnectedOrPending();
    }

    public boolean isHearingAidDeviceOn() {
        return mBluetoothRouteManager.isCachedHearingAidDevice(
                mBluetoothRouteManager.getBluetoothAudioConnectedDevice());
    }

    public boolean isLeAudioDeviceOn() {
        return mBluetoothRouteManager.isCachedLeAudioDevice(
                mBluetoothRouteManager.getBluetoothAudioConnectedDevice());
    }

    @Override
    public void onBluetoothDeviceListChanged() {
        mCallAudioAdapter.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BLUETOOTH_DEVICE_LIST_CHANGED);
    }

    @Override
    public void onBluetoothActiveDevicePresent() {
        mCallAudioAdapter.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT);
    }

    @Override
    public void onBluetoothActiveDeviceGone() {
        mCallAudioAdapter.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE);
    }

    @Override
    public void onBluetoothAudioConnected() {
        mRingtonePlayer.updateBtActiveState(true);
        mCallAudioAdapter.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_AUDIO_CONNECTED);
    }

    @Override
    public void onBluetoothAudioConnecting() {
        mRingtonePlayer.updateBtActiveState(false);
        // Pretend like audio is connected when communicating w/ CARSM.
        mCallAudioAdapter.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_AUDIO_CONNECTED);
    }

    @Override
    public void onBluetoothAudioDisconnected() {
        mRingtonePlayer.updateBtActiveState(false);
        mCallAudioAdapter.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_AUDIO_DISCONNECTED);
    }

    @Override
    public void onUnexpectedBluetoothStateChange() {
        mCallAudioAdapter.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE);
    }

    /**
      * Updates the audio route when the headset plugged in state changes. For example, if audio is
      * being routed over speakerphone and a headset is plugged in then switch to wired headset.
      */
    @Override
    public void onWiredHeadsetPluggedInChanged(boolean oldIsPluggedIn, boolean newIsPluggedIn) {
        if (!oldIsPluggedIn && newIsPluggedIn) {
            mCallAudioAdapter.sendMessageWithSessionInfo(
                    CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET);
        } else if (oldIsPluggedIn && !newIsPluggedIn){
            mCallAudioAdapter.sendMessageWithSessionInfo(
                    CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET);
        }
    }

    @Override
    public void onDockChanged(boolean isDocked) {
        mCallAudioAdapter.sendMessageWithSessionInfo(
                isDocked ? CallAudioRouteStateMachine.CONNECT_DOCK
                        : CallAudioRouteStateMachine.DISCONNECT_DOCK
        );
    }
}
+2 −11
Original line number Diff line number Diff line
@@ -742,13 +742,6 @@ public class CallsManager extends Call.ListenerBase
        bluetoothStateReceiver.setCallAudioRouteAdapter(mCallAudioRouteAdapter);
        bluetoothDeviceManager.setCallAudioRouteAdapter(mCallAudioRouteAdapter);

        CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter =
                new CallAudioRoutePeripheralAdapter(
                        mCallAudioRouteAdapter,
                        bluetoothManager,
                        wiredHeadsetManager,
                        mDockManager,
                        asyncRingtonePlayer);
        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        InCallTonePlayer.MediaPlayerFactory mediaPlayerFactory = (resourceId, attributes) -> {
          MediaPlayer mediaPlayer;
@@ -761,10 +754,8 @@ public class CallsManager extends Call.ListenerBase
          }
          return new InCallTonePlayer.MediaPlayerAdapterImpl(mediaPlayer);
        };
        InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory(
                callAudioRoutePeripheralAdapter, lock, toneGeneratorFactory, mediaPlayerFactory,
                () -> audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0, featureFlags,
                Looper.getMainLooper());
        InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory(lock,
                toneGeneratorFactory, mediaPlayerFactory, Looper.getMainLooper());

        SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil();
        RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context, featureFlags);
+7 −56
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.telecom.Logging.Runnable;
import android.telecom.Logging.Session;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.telecom.flags.FeatureFlags;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -50,24 +49,16 @@ public class InCallTonePlayer extends Thread {
     */
    public static class Factory {
        private CallAudioManager mCallAudioManager;
        private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter;
        private final TelecomSystem.SyncRoot mLock;
        private final ToneGeneratorFactory mToneGeneratorFactory;
        private final MediaPlayerFactory mMediaPlayerFactory;
        private final AudioManagerAdapter mAudioManagerAdapter;
        private final FeatureFlags mFeatureFlags;
        private final Looper mLooper;

        public Factory(CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter,
                TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory,
                MediaPlayerFactory mediaPlayerFactory, AudioManagerAdapter audioManagerAdapter,
                FeatureFlags flags, Looper looper) {
            mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter;
        public Factory(TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory,
                MediaPlayerFactory mediaPlayerFactory, Looper looper) {
            mLock = lock;
            mToneGeneratorFactory = toneGeneratorFactory;
            mMediaPlayerFactory = mediaPlayerFactory;
            mAudioManagerAdapter = audioManagerAdapter;
            mFeatureFlags = flags;
            mLooper = looper;
        }

@@ -76,9 +67,8 @@ public class InCallTonePlayer extends Thread {
        }

        public InCallTonePlayer createPlayer(Call call, int tone) {
            return new InCallTonePlayer(call, tone, mCallAudioManager,
                    mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory,
                    mMediaPlayerFactory, mAudioManagerAdapter, mFeatureFlags, mLooper);
            return new InCallTonePlayer(call, tone, mCallAudioManager, mLock, mToneGeneratorFactory,
                    mMediaPlayerFactory, mLooper);
        }
    }

@@ -95,7 +85,7 @@ public class InCallTonePlayer extends Thread {
    }

    public static class MediaPlayerAdapterImpl implements MediaPlayerAdapter {
        private MediaPlayer mMediaPlayer;
        private final MediaPlayer mMediaPlayer;

        /**
         * Create new media player adapter backed by a real mediaplayer.
@@ -149,10 +139,6 @@ public class InCallTonePlayer extends Thread {
        MediaPlayerAdapter get (int resourceId, AudioAttributes attributes);
    }

    public interface AudioManagerAdapter {
        boolean isVolumeOverZero();
    }

    // The possible tones that we can play.
    public static final int TONE_INVALID = 0;
    public static final int TONE_BUSY = 1;
@@ -174,7 +160,6 @@ public class InCallTonePlayer extends Thread {

    private static final int TONE_RESOURCE_ID_UNDEFINED = -1;

    private static final int RELATIVE_VOLUME_EMERGENCY = 100;
    private static final int RELATIVE_VOLUME_HIPRI = 80;
    private static final int RELATIVE_VOLUME_LOPRI = 30;
    private static final int RELATIVE_VOLUME_UNDEFINED = -1;
@@ -196,10 +181,9 @@ public class InCallTonePlayer extends Thread {
     * when we need focus and when it can be release. This should only be manipulated from the main
     * thread.
     */
    private static AtomicInteger sTonesPlaying = new AtomicInteger(0);
    private static final AtomicInteger sTonesPlaying = new AtomicInteger(0);

    private final CallAudioManager mCallAudioManager;
    private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter;

    private final Handler mMainThreadHandler;

@@ -221,8 +205,6 @@ public class InCallTonePlayer extends Thread {
    private final Call mCall;
    private final ToneGeneratorFactory mToneGenerator;
    private final MediaPlayerFactory mMediaPlayerFactory;
    private final AudioManagerAdapter mAudioManagerAdapter;
    private final FeatureFlags mFeatureFlags;

    /**
     * Latch used for awaiting on playback, which may be interrupted if the tone is stopped from
@@ -239,23 +221,17 @@ public class InCallTonePlayer extends Thread {
            Call call,
            int toneId,
            CallAudioManager callAudioManager,
            CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter,
            TelecomSystem.SyncRoot lock,
            ToneGeneratorFactory toneGeneratorFactory,
            MediaPlayerFactory mediaPlayerFactor,
            AudioManagerAdapter audioManagerAdapter,
            FeatureFlags flags,
            Looper looper) {
        mCall = call;
        mState = STATE_OFF;
        mToneId = toneId;
        mCallAudioManager = callAudioManager;
        mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter;
        mLock = lock;
        mToneGenerator = toneGeneratorFactory;
        mMediaPlayerFactory = mediaPlayerFactor;
        mAudioManagerAdapter = audioManagerAdapter;
        mFeatureFlags = flags;
        mMainThreadHandler = new Handler(looper);
    }

@@ -375,7 +351,7 @@ public class InCallTonePlayer extends Thread {
                    throw new IllegalStateException("Bad toneId: " + mToneId);
            }

            int stream = getStreamType(toneType);
            int stream = AudioManager.STREAM_VOICE_CALL;
            if (toneType != ToneGenerator.TONE_UNKNOWN) {
                playToneGeneratorTone(stream, toneVolume, toneType, toneLengthMillis);
            } else if (mediaResourceId != TONE_RESOURCE_ID_UNDEFINED) {
@@ -387,31 +363,6 @@ public class InCallTonePlayer extends Thread {
        }
    }

    /**
     * @param toneType The ToneGenerator tone type
     * @return The ToneGenerator stream type
     */
    private int getStreamType(int toneType) {
        if (mFeatureFlags.useStreamVoiceCallTones()) {
            return AudioManager.STREAM_VOICE_CALL;
        }

        int stream = AudioManager.STREAM_VOICE_CALL;
        if (mCallAudioRoutePeripheralAdapter.isBluetoothAudioOn()) {
            stream = AudioManager.STREAM_BLUETOOTH_SCO;
        }
        if (toneType != ToneGenerator.TONE_UNKNOWN) {
            if (stream == AudioManager.STREAM_BLUETOOTH_SCO) {
                // Override audio stream for BT le device and hearing aid device
                if (mCallAudioRoutePeripheralAdapter.isLeAudioDeviceOn()
                        || mCallAudioRoutePeripheralAdapter.isHearingAidDeviceOn()) {
                    stream = AudioManager.STREAM_VOICE_CALL;
                }
            }
        }
        return stream;
    }

    /**
     * Play a tone generated by the {@link ToneGenerator}.
     * @param stream The stream on which the tone will be played.
+0 −200
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.server.telecom.tests;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import androidx.test.filters.SmallTest;

import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.CallAudioRoutePeripheralAdapter;
import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.DockManager;
import com.android.server.telecom.WiredHeadsetManager;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;

@RunWith(JUnit4.class)
public class CallAudioRoutePeripheralAdapterTest extends TelecomTestCase {
    CallAudioRoutePeripheralAdapter mAdapter;

    @Mock private CallAudioRouteStateMachine mCallAudioRouteStateMachine;
    @Mock private BluetoothRouteManager mBluetoothRouteManager;
    @Mock private WiredHeadsetManager mWiredHeadsetManager;
    @Mock private DockManager mDockManager;
    @Mock private AsyncRingtonePlayer mRingtonePlayer;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();

        mAdapter = new CallAudioRoutePeripheralAdapter(
                mCallAudioRouteStateMachine,
                mBluetoothRouteManager,
                mWiredHeadsetManager,
                mDockManager,
                mRingtonePlayer);
    }

    @Override
    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }

    @SmallTest
    @Test
    public void testIsBluetoothAudioOn() {
        when(mBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
        assertFalse(mAdapter.isBluetoothAudioOn());

        when(mBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(true);
        assertTrue(mAdapter.isBluetoothAudioOn());
    }

    @SmallTest
    @Test
    public void testIsHearingAidDeviceOn() {
        when(mBluetoothRouteManager.isCachedHearingAidDevice(any())).thenReturn(false);
        assertFalse(mAdapter.isHearingAidDeviceOn());

        when(mBluetoothRouteManager.isCachedHearingAidDevice(any())).thenReturn(true);
        assertTrue(mAdapter.isHearingAidDeviceOn());
    }

    @SmallTest
    @Test
    public void testIsLeAudioDeviceOn() {
        when(mBluetoothRouteManager.isCachedLeAudioDevice(any())).thenReturn(false);
        assertFalse(mAdapter.isLeAudioDeviceOn());

        when(mBluetoothRouteManager.isCachedLeAudioDevice(any())).thenReturn(true);
        assertTrue(mAdapter.isLeAudioDeviceOn());
    }

    @SmallTest
    @Test
    public void testOnBluetoothDeviceListChanged() {
        mAdapter.onBluetoothDeviceListChanged();
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BLUETOOTH_DEVICE_LIST_CHANGED);
    }

    @SmallTest
    @Test
    public void testOnBluetoothActiveDevicePresent() {
        mAdapter.onBluetoothActiveDevicePresent();
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_PRESENT);
    }

    @SmallTest
    @Test
    public void testOnBluetoothActiveDeviceGone() {
        mAdapter.onBluetoothActiveDeviceGone();
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_ACTIVE_DEVICE_GONE);
    }

    @SmallTest
    @Test
    public void testOnBluetoothAudioConnected() {
        mAdapter.onBluetoothAudioConnected();
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_AUDIO_CONNECTED);
        verify(mRingtonePlayer).updateBtActiveState(true);
    }

    @SmallTest
    @Test
    public void testOnBluetoothAudioConnecting() {
        mAdapter.onBluetoothAudioConnecting();
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_AUDIO_CONNECTED);
        verify(mRingtonePlayer).updateBtActiveState(false);
    }

    @SmallTest
    @Test
    public void testOnBluetoothAudioDisconnected() {
        mAdapter.onBluetoothAudioDisconnected();
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.BT_AUDIO_DISCONNECTED);
        verify(mRingtonePlayer).updateBtActiveState(false);
    }

    @SmallTest
    @Test
    public void testOnUnexpectedBluetoothStateChange() {
        mAdapter.onUnexpectedBluetoothStateChange();
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE);
    }

    @SmallTest
    @Test
    public void testOnWiredHeadsetPluggedInChangedNoChange() {
        mAdapter.onWiredHeadsetPluggedInChanged(false, false);
        mAdapter.onWiredHeadsetPluggedInChanged(true, true);
        verify(mCallAudioRouteStateMachine, never()).sendMessageWithSessionInfo(anyInt());
    }

    @SmallTest
    @Test
    public void testOnWiredHeadsetPluggedInChangedPlugged() {
        mAdapter.onWiredHeadsetPluggedInChanged(false, true);
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET);
    }

    @SmallTest
    @Test
    public void testOnWiredHeadsetPluggedInChangedUnplugged() {
        mAdapter.onWiredHeadsetPluggedInChanged(true, false);
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET);
    }

    @SmallTest
    @Test
    public void testOnDockChangedConnected() {
        mAdapter.onDockChanged(true);
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.CONNECT_DOCK);
    }

    @SmallTest
    @Test
    public void testOnDockChangedDisconnected() {
        mAdapter.onDockChanged(false);
        verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.DISCONNECT_DOCK);
    }
}
Loading