Loading res/raw/endcall.ogg 0 → 100644 +19.2 KiB File added.No diff preview for this file type. View file src/com/android/server/telecom/CallsManager.java +7 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.IntentFilter; import android.media.AudioManager; import android.media.AudioSystem; import android.media.ToneGenerator; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Handler; Loading Loading @@ -408,8 +409,12 @@ public class CallsManager extends Call.ListenerBase wiredHeadsetManager, mDockManager); AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); InCallTonePlayer.MediaPlayerFactory mediaPlayerFactory = (resourceId, attributes) -> MediaPlayer.create(mContext, resourceId, attributes, audioManager.generateAudioSessionId()); InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory( callAudioRoutePeripheralAdapter, lock, toneGeneratorFactory); callAudioRoutePeripheralAdapter, lock, toneGeneratorFactory, mediaPlayerFactory); SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil(); RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context); Loading @@ -419,8 +424,7 @@ public class CallsManager extends Call.ListenerBase emergencyCallHelper); mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer, ringtoneFactory, systemVibrator, mInCallController); mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext, (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE), mLock); mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext, audioManager, mLock); mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine, this, callAudioModeStateMachineFactory.create((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)), Loading src/com/android/server/telecom/InCallTonePlayer.java +104 −14 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.server.telecom; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.ToneGenerator; import android.os.Handler; import android.os.Looper; Loading @@ -27,9 +29,11 @@ import android.telecom.Logging.Session; import com.android.internal.annotations.VisibleForTesting; /** * Play a call-related tone (ringback, busy signal, etc.) through ToneGenerator. To use, create an * instance using InCallTonePlayer.Factory (passing in the TONE_* constant for the tone you want) * and start() it. Implemented on top of {@link Thread} so that the tone plays in its own thread. * Play a call-related tone (ringback, busy signal, etc.) either through ToneGenerator, or using a * media resource file. * To use, create an instance using InCallTonePlayer.Factory (passing in the TONE_* constant for * the tone you want) and start() it. Implemented on top of {@link Thread} so that the tone plays in * its own thread. */ public class InCallTonePlayer extends Thread { Loading @@ -41,12 +45,15 @@ public class InCallTonePlayer extends Thread { private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter; private final TelecomSystem.SyncRoot mLock; private final ToneGeneratorFactory mToneGeneratorFactory; private final MediaPlayerFactory mMediaPlayerFactory; Factory(CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory) { TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory, MediaPlayerFactory mediaPlayerFactory) { mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter; mLock = lock; mToneGeneratorFactory = toneGeneratorFactory; mMediaPlayerFactory = mediaPlayerFactory; } public void setCallAudioManager(CallAudioManager callAudioManager) { Loading @@ -55,7 +62,8 @@ public class InCallTonePlayer extends Thread { public InCallTonePlayer createPlayer(int tone) { return new InCallTonePlayer(tone, mCallAudioManager, mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory); mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory, mMediaPlayerFactory); } } Loading @@ -63,6 +71,10 @@ public class InCallTonePlayer extends Thread { ToneGenerator get (int streamType, int volume); } public interface MediaPlayerFactory { MediaPlayer get (int resourceId, AudioAttributes attributes); } // The possible tones that we can play. public static final int TONE_INVALID = 0; public static final int TONE_BUSY = 1; Loading @@ -80,9 +92,12 @@ public class InCallTonePlayer extends Thread { public static final int TONE_VOICE_PRIVACY = 13; public static final int TONE_VIDEO_UPGRADE = 14; 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 = 50; private static final int RELATIVE_VOLUME_UNDEFINED = -1; // Buffer time (in msec) to add on to the tone timeout value. Needed mainly when the timeout // value for a tone is exact duration of the tone itself. Loading Loading @@ -111,6 +126,9 @@ public class InCallTonePlayer extends Thread { /** Current state of the tone player. */ private int mState; /** For tones which are not generated using ToneGenerator. */ private MediaPlayer mToneMediaPlayer = null; /** Telecom lock object. */ private final TelecomSystem.SyncRoot mLock; Loading @@ -118,6 +136,7 @@ public class InCallTonePlayer extends Thread { private final Object mSessionLock = new Object(); private final ToneGeneratorFactory mToneGenerator; private final MediaPlayerFactory mMediaPlayerFactory; /** * Initializes the tone player. Private; use the {@link Factory} to create tone players. Loading @@ -129,19 +148,20 @@ public class InCallTonePlayer extends Thread { CallAudioManager callAudioManager, CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory) { ToneGeneratorFactory toneGeneratorFactory, MediaPlayerFactory mediaPlayerFactor) { mState = STATE_OFF; mToneId = toneId; mCallAudioManager = callAudioManager; mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter; mLock = lock; mToneGenerator = toneGeneratorFactory; mMediaPlayerFactory = mediaPlayerFactor; } /** {@inheritDoc} */ @Override public void run() { ToneGenerator toneGenerator = null; try { synchronized (mSessionLock) { if (mSession != null) { Loading @@ -154,6 +174,8 @@ public class InCallTonePlayer extends Thread { final int toneType; // Passed to ToneGenerator.startTone. final int toneVolume; // Passed to the ToneGenerator constructor. final int toneLengthMillis; final int mediaResourceId; // The resourceId of the tone to play. Used for media-based // tones. switch (mToneId) { case TONE_BUSY: Loading @@ -161,11 +183,16 @@ public class InCallTonePlayer extends Thread { toneType = ToneGenerator.TONE_SUP_BUSY; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_CALL_ENDED: toneType = ToneGenerator.TONE_PROP_PROMPT; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 200; // Don't use tone generator toneType = ToneGenerator.TONE_UNKNOWN; toneVolume = RELATIVE_VOLUME_UNDEFINED; toneLengthMillis = 0; // Use a tone resource file for a more rich, full-bodied tone experience. mediaResourceId = R.raw.endcall; break; case TONE_OTA_CALL_ENDED: // TODO: fill in Loading @@ -174,46 +201,55 @@ public class InCallTonePlayer extends Thread { toneType = ToneGenerator.TONE_SUP_CALL_WAITING; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_CDMA_DROP: toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; toneVolume = RELATIVE_VOLUME_LOPRI; toneLengthMillis = 375; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_CONGESTION: toneType = ToneGenerator.TONE_SUP_CONGESTION; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_INTERCEPT: toneType = ToneGenerator.TONE_CDMA_ABBR_INTERCEPT; toneVolume = RELATIVE_VOLUME_LOPRI; toneLengthMillis = 500; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_OUT_OF_SERVICE: toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; toneVolume = RELATIVE_VOLUME_LOPRI; toneLengthMillis = 375; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_REDIAL: toneType = ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE; toneVolume = RELATIVE_VOLUME_LOPRI; toneLengthMillis = 5000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_REORDER: toneType = ToneGenerator.TONE_CDMA_REORDER; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_RING_BACK: toneType = ToneGenerator.TONE_SUP_RINGTONE; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_UNOBTAINABLE_NUMBER: toneType = ToneGenerator.TONE_SUP_ERROR; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_VOICE_PRIVACY: // TODO: fill in. Loading @@ -223,6 +259,7 @@ public class InCallTonePlayer extends Thread { toneType = ToneGenerator.TONE_SUP_CALL_WAITING; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; default: throw new IllegalStateException("Bad toneId: " + mToneId); Loading @@ -233,16 +270,38 @@ public class InCallTonePlayer extends Thread { stream = AudioManager.STREAM_BLUETOOTH_SCO; } if (toneType != ToneGenerator.TONE_UNKNOWN) { playToneGeneratorTone(stream, toneVolume, toneType, toneLengthMillis); } else if (mediaResourceId != TONE_RESOURCE_ID_UNDEFINED) { playMediaTone(stream, mediaResourceId); } } finally { cleanUpTonePlayer(); Log.endSession(); } } /** * Play a tone generated by the {@link ToneGenerator}. * @param stream The stream on which the tone will be played. * @param toneVolume The volume of the tone. * @param toneType The type of tone to play. * @param toneLengthMillis How long to play the tone. */ private void playToneGeneratorTone(int stream, int toneVolume, int toneType, int toneLengthMillis) { ToneGenerator toneGenerator = null; try { // If the ToneGenerator creation fails, just continue without it. It is a local audio // signal, and is not as important. try { Log.v(this, "Creating generator"); toneGenerator = mToneGenerator.get(stream, toneVolume); } catch (RuntimeException e) { Log.w(this, "Failed to create ToneGenerator.", e); return; } Log.i(this, "playToneGeneratorTone: toneType=%d", toneType); // TODO: Certain CDMA tones need to check the ringer-volume state before // playing. See CallNotifier.InCallTonePlayer. Loading @@ -267,11 +326,42 @@ public class InCallTonePlayer extends Thread { if (toneGenerator != null) { toneGenerator.release(); } cleanUpTonePlayer(); Log.endSession(); } } /** * Plays an audio-file based media tone. * @param stream The audio stream on which to play the tone. * @param toneResourceId The resource ID of the tone to play. */ private void playMediaTone(int stream, int toneResourceId) { synchronized (this) { if (mState != STATE_STOPPED) { mState = STATE_ON; } Log.i(this, "playMediaTone: toneResourceId=%d", toneResourceId); AudioAttributes attributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .setLegacyStreamType(stream) .build(); mToneMediaPlayer = mMediaPlayerFactory.get(toneResourceId, attributes); mToneMediaPlayer.setLooping(false); mToneMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { synchronized (this) { mState = STATE_OFF; } mToneMediaPlayer.release(); mToneMediaPlayer = null; } }); mToneMediaPlayer.start(); } } @VisibleForTesting public void startTone() { sTonesPlaying++; Loading Loading
src/com/android/server/telecom/CallsManager.java +7 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.IntentFilter; import android.media.AudioManager; import android.media.AudioSystem; import android.media.ToneGenerator; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Handler; Loading Loading @@ -408,8 +409,12 @@ public class CallsManager extends Call.ListenerBase wiredHeadsetManager, mDockManager); AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); InCallTonePlayer.MediaPlayerFactory mediaPlayerFactory = (resourceId, attributes) -> MediaPlayer.create(mContext, resourceId, attributes, audioManager.generateAudioSessionId()); InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory( callAudioRoutePeripheralAdapter, lock, toneGeneratorFactory); callAudioRoutePeripheralAdapter, lock, toneGeneratorFactory, mediaPlayerFactory); SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil(); RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context); Loading @@ -419,8 +424,7 @@ public class CallsManager extends Call.ListenerBase emergencyCallHelper); mRinger = new Ringer(playerFactory, context, systemSettingsUtil, asyncRingtonePlayer, ringtoneFactory, systemVibrator, mInCallController); mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext, (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE), mLock); mCallRecordingTonePlayer = new CallRecordingTonePlayer(mContext, audioManager, mLock); mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine, this, callAudioModeStateMachineFactory.create((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)), Loading
src/com/android/server/telecom/InCallTonePlayer.java +104 −14 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.server.telecom; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.ToneGenerator; import android.os.Handler; import android.os.Looper; Loading @@ -27,9 +29,11 @@ import android.telecom.Logging.Session; import com.android.internal.annotations.VisibleForTesting; /** * Play a call-related tone (ringback, busy signal, etc.) through ToneGenerator. To use, create an * instance using InCallTonePlayer.Factory (passing in the TONE_* constant for the tone you want) * and start() it. Implemented on top of {@link Thread} so that the tone plays in its own thread. * Play a call-related tone (ringback, busy signal, etc.) either through ToneGenerator, or using a * media resource file. * To use, create an instance using InCallTonePlayer.Factory (passing in the TONE_* constant for * the tone you want) and start() it. Implemented on top of {@link Thread} so that the tone plays in * its own thread. */ public class InCallTonePlayer extends Thread { Loading @@ -41,12 +45,15 @@ public class InCallTonePlayer extends Thread { private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter; private final TelecomSystem.SyncRoot mLock; private final ToneGeneratorFactory mToneGeneratorFactory; private final MediaPlayerFactory mMediaPlayerFactory; Factory(CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory) { TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory, MediaPlayerFactory mediaPlayerFactory) { mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter; mLock = lock; mToneGeneratorFactory = toneGeneratorFactory; mMediaPlayerFactory = mediaPlayerFactory; } public void setCallAudioManager(CallAudioManager callAudioManager) { Loading @@ -55,7 +62,8 @@ public class InCallTonePlayer extends Thread { public InCallTonePlayer createPlayer(int tone) { return new InCallTonePlayer(tone, mCallAudioManager, mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory); mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory, mMediaPlayerFactory); } } Loading @@ -63,6 +71,10 @@ public class InCallTonePlayer extends Thread { ToneGenerator get (int streamType, int volume); } public interface MediaPlayerFactory { MediaPlayer get (int resourceId, AudioAttributes attributes); } // The possible tones that we can play. public static final int TONE_INVALID = 0; public static final int TONE_BUSY = 1; Loading @@ -80,9 +92,12 @@ public class InCallTonePlayer extends Thread { public static final int TONE_VOICE_PRIVACY = 13; public static final int TONE_VIDEO_UPGRADE = 14; 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 = 50; private static final int RELATIVE_VOLUME_UNDEFINED = -1; // Buffer time (in msec) to add on to the tone timeout value. Needed mainly when the timeout // value for a tone is exact duration of the tone itself. Loading Loading @@ -111,6 +126,9 @@ public class InCallTonePlayer extends Thread { /** Current state of the tone player. */ private int mState; /** For tones which are not generated using ToneGenerator. */ private MediaPlayer mToneMediaPlayer = null; /** Telecom lock object. */ private final TelecomSystem.SyncRoot mLock; Loading @@ -118,6 +136,7 @@ public class InCallTonePlayer extends Thread { private final Object mSessionLock = new Object(); private final ToneGeneratorFactory mToneGenerator; private final MediaPlayerFactory mMediaPlayerFactory; /** * Initializes the tone player. Private; use the {@link Factory} to create tone players. Loading @@ -129,19 +148,20 @@ public class InCallTonePlayer extends Thread { CallAudioManager callAudioManager, CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory) { ToneGeneratorFactory toneGeneratorFactory, MediaPlayerFactory mediaPlayerFactor) { mState = STATE_OFF; mToneId = toneId; mCallAudioManager = callAudioManager; mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter; mLock = lock; mToneGenerator = toneGeneratorFactory; mMediaPlayerFactory = mediaPlayerFactor; } /** {@inheritDoc} */ @Override public void run() { ToneGenerator toneGenerator = null; try { synchronized (mSessionLock) { if (mSession != null) { Loading @@ -154,6 +174,8 @@ public class InCallTonePlayer extends Thread { final int toneType; // Passed to ToneGenerator.startTone. final int toneVolume; // Passed to the ToneGenerator constructor. final int toneLengthMillis; final int mediaResourceId; // The resourceId of the tone to play. Used for media-based // tones. switch (mToneId) { case TONE_BUSY: Loading @@ -161,11 +183,16 @@ public class InCallTonePlayer extends Thread { toneType = ToneGenerator.TONE_SUP_BUSY; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_CALL_ENDED: toneType = ToneGenerator.TONE_PROP_PROMPT; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 200; // Don't use tone generator toneType = ToneGenerator.TONE_UNKNOWN; toneVolume = RELATIVE_VOLUME_UNDEFINED; toneLengthMillis = 0; // Use a tone resource file for a more rich, full-bodied tone experience. mediaResourceId = R.raw.endcall; break; case TONE_OTA_CALL_ENDED: // TODO: fill in Loading @@ -174,46 +201,55 @@ public class InCallTonePlayer extends Thread { toneType = ToneGenerator.TONE_SUP_CALL_WAITING; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_CDMA_DROP: toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; toneVolume = RELATIVE_VOLUME_LOPRI; toneLengthMillis = 375; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_CONGESTION: toneType = ToneGenerator.TONE_SUP_CONGESTION; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_INTERCEPT: toneType = ToneGenerator.TONE_CDMA_ABBR_INTERCEPT; toneVolume = RELATIVE_VOLUME_LOPRI; toneLengthMillis = 500; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_OUT_OF_SERVICE: toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; toneVolume = RELATIVE_VOLUME_LOPRI; toneLengthMillis = 375; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_REDIAL: toneType = ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE; toneVolume = RELATIVE_VOLUME_LOPRI; toneLengthMillis = 5000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_REORDER: toneType = ToneGenerator.TONE_CDMA_REORDER; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_RING_BACK: toneType = ToneGenerator.TONE_SUP_RINGTONE; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_UNOBTAINABLE_NUMBER: toneType = ToneGenerator.TONE_SUP_ERROR; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; case TONE_VOICE_PRIVACY: // TODO: fill in. Loading @@ -223,6 +259,7 @@ public class InCallTonePlayer extends Thread { toneType = ToneGenerator.TONE_SUP_CALL_WAITING; toneVolume = RELATIVE_VOLUME_HIPRI; toneLengthMillis = 4000; mediaResourceId = TONE_RESOURCE_ID_UNDEFINED; break; default: throw new IllegalStateException("Bad toneId: " + mToneId); Loading @@ -233,16 +270,38 @@ public class InCallTonePlayer extends Thread { stream = AudioManager.STREAM_BLUETOOTH_SCO; } if (toneType != ToneGenerator.TONE_UNKNOWN) { playToneGeneratorTone(stream, toneVolume, toneType, toneLengthMillis); } else if (mediaResourceId != TONE_RESOURCE_ID_UNDEFINED) { playMediaTone(stream, mediaResourceId); } } finally { cleanUpTonePlayer(); Log.endSession(); } } /** * Play a tone generated by the {@link ToneGenerator}. * @param stream The stream on which the tone will be played. * @param toneVolume The volume of the tone. * @param toneType The type of tone to play. * @param toneLengthMillis How long to play the tone. */ private void playToneGeneratorTone(int stream, int toneVolume, int toneType, int toneLengthMillis) { ToneGenerator toneGenerator = null; try { // If the ToneGenerator creation fails, just continue without it. It is a local audio // signal, and is not as important. try { Log.v(this, "Creating generator"); toneGenerator = mToneGenerator.get(stream, toneVolume); } catch (RuntimeException e) { Log.w(this, "Failed to create ToneGenerator.", e); return; } Log.i(this, "playToneGeneratorTone: toneType=%d", toneType); // TODO: Certain CDMA tones need to check the ringer-volume state before // playing. See CallNotifier.InCallTonePlayer. Loading @@ -267,11 +326,42 @@ public class InCallTonePlayer extends Thread { if (toneGenerator != null) { toneGenerator.release(); } cleanUpTonePlayer(); Log.endSession(); } } /** * Plays an audio-file based media tone. * @param stream The audio stream on which to play the tone. * @param toneResourceId The resource ID of the tone to play. */ private void playMediaTone(int stream, int toneResourceId) { synchronized (this) { if (mState != STATE_STOPPED) { mState = STATE_ON; } Log.i(this, "playMediaTone: toneResourceId=%d", toneResourceId); AudioAttributes attributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .setLegacyStreamType(stream) .build(); mToneMediaPlayer = mMediaPlayerFactory.get(toneResourceId, attributes); mToneMediaPlayer.setLooping(false); mToneMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { synchronized (this) { mState = STATE_OFF; } mToneMediaPlayer.release(); mToneMediaPlayer = null; } }); mToneMediaPlayer.start(); } } @VisibleForTesting public void startTone() { sTonesPlaying++; Loading