Audio focus

This commit is contained in:
Christopher Eby 2012-01-06 08:24:12 -06:00
parent 95b5965a12
commit 61a12c6140
2 changed files with 92 additions and 26 deletions

View File

@ -30,19 +30,58 @@ import android.media.AudioManager;
/**
* Framework methods only in Froyo or above go here.
*/
public class CompatFroyo {
public class CompatFroyo implements AudioManager.OnAudioFocusChangeListener {
/**
* Instance of the audio focus listener created by {@link #createAudioFocus()}.
*/
private static CompatFroyo sAudioFocus;
/**
* Calls {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)}.
*/
public static void registerMediaButtonEventReceiver(AudioManager manager, ComponentName receiver)
{
manager.registerMediaButtonEventReceiver(receiver);
}
/**
* Calls {@link AudioManager#unregisterMediaButtonEventReceiver(ComponentName)}.
*/
public static void unregisterMediaButtonEventReceiver(AudioManager manager, ComponentName receiver)
{
manager.unregisterMediaButtonEventReceiver(receiver);
}
/**
* Calls {@link BackupManager#dataChanged()}.
*/
public static void dataChanged(Context context)
{
new BackupManager(context).dataChanged();
}
/**
* Creates an audio focus listener that calls back to {@link PlaybackService#onAudioFocusChange(int)}.
*/
public static void createAudioFocus()
{
sAudioFocus = new CompatFroyo();
}
/**
* Calls {@link AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int)}
*/
public static void requestAudioFocus(AudioManager manager)
{
manager.requestAudioFocus(sAudioFocus, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}
@Override
public void onAudioFocusChange(int type)
{
PlaybackService service = PlaybackService.sInstance;
if (service != null) {
service.onAudioFocusChange(type);
}
}
}

View File

@ -216,8 +216,11 @@ public final class PlaybackService extends Service
*/
private static final long IDLE_GRACE_PERIOD = 60000;
private static final Object sWait = new Object();
private static PlaybackService sInstance;
private static final Object sWait = new Object[0];
/**
* The appplication-wide instance of the PlaybackService.
*/
public static PlaybackService sInstance;
private static final ArrayList<PlaybackActivity> sActivities = new ArrayList<PlaybackActivity>(5);
/**
* Cached app-wide SharedPreferences instance.
@ -300,6 +303,10 @@ public final class PlaybackService extends Service
* indicates that no timeout has occurred.
*/
private long mIdleStart = -1;
/**
* True if the last audio focus loss can be ducked.
*/
private boolean mDuckedLoss;
@Override
public void onCreate()
@ -319,6 +326,10 @@ public final class PlaybackService extends Service
mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
CompatFroyo.createAudioFocus();
}
SharedPreferences settings = getSettings(this);
settings.registerOnSharedPreferenceChangeListener(this);
mNotificationMode = Integer.parseInt(settings.getString("notification_mode", "1"));
@ -335,13 +346,26 @@ public final class PlaybackService extends Service
mHeadsetPlay = settings.getBoolean("headset_play", false);
mInvertNotification = settings.getBoolean("notification_inverted_color", false);
mNotificationAction = createNotificationAction(settings);
mHeadsetPause = getSettings(this).getBoolean("headset_pause", true);
PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VanillaMusicLock");
mCallListener = new InCallListener();
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(mCallListener, PhoneStateListener.LISTEN_CALL_STATE);
mReceiver = new Receiver();
IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
filter.addAction(Intent.ACTION_HEADSET_PLUG);
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mReceiver, filter);
getContentResolver().registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mObserver);
mLooper = thread.getLooper();
mHandler = new Handler(mLooper, this);
mHandler.sendEmptyMessage(POST_CREATE);
initWidgets();
@ -556,6 +580,9 @@ public final class PlaybackService extends Service
if (mNotificationMode != NEVER)
startForeground(NOTIFICATION_ID, createNotification(mCurrentSong, mState));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
CompatFroyo.requestAudioFocus(mAudioManager);
}
if (mWakeLock != null)
mWakeLock.acquire();
} else {
@ -968,18 +995,6 @@ public final class PlaybackService extends Service
loadPreference(key);
}
private void setupReceiver()
{
if (mReceiver == null)
mReceiver = new Receiver();
IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
filter.addAction(Intent.ACTION_HEADSET_PLUG);
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mReceiver, filter);
}
private static final int POST_CREATE = 1;
/**
* Run the given query and add the results to the timeline.
*
@ -1030,16 +1045,6 @@ public final class PlaybackService extends Service
case QUERY:
runQuery(message.arg1, (QueryTask)message.obj, message.arg2);
break;
case POST_CREATE:
mHeadsetPause = getSettings(this).getBoolean("headset_pause", true);
setupReceiver();
mCallListener = new InCallListener();
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(mCallListener, PhoneStateListener.LISTEN_CALL_STATE);
getContentResolver().registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mObserver);
break;
case IDLE_TIMEOUT:
if ((mState & FLAG_PLAYING) != 0)
mHandler.sendMessage(mHandler.obtainMessage(FADE_OUT, 100, 0));
@ -1511,4 +1516,26 @@ public final class PlaybackService extends Service
notification.contentIntent = mNotificationAction;
return notification;
}
public void onAudioFocusChange(int type)
{
Log.d("VanillaMusic", "audio focus change: " + type);
switch (type) {
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
mDuckedLoss = (mState & FLAG_PLAYING) != 0;
unsetFlag(FLAG_PLAYING);
break;
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
mDuckedLoss = false;
unsetFlag(FLAG_PLAYING);
break;
case AudioManager.AUDIOFOCUS_GAIN:
if (mDuckedLoss) {
mDuckedLoss = false;
setFlag(FLAG_PLAYING);
}
break;
}
}
}