Loading android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java +82 −111 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.bluetooth.avrcp; import static java.util.Objects.requireNonNull; import android.annotation.NonNull; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; Loading Loading @@ -62,14 +64,18 @@ public class AvrcpTargetService extends ProfileService { private final BluetoothEventLogger mMediaKeyEventLogger = new BluetoothEventLogger(MEDIA_KEY_EVENT_LOGGER_SIZE, MEDIA_KEY_EVENT_LOGGER_TITLE); private AvrcpVersion mAvrcpVersion; private MediaPlayerList mMediaPlayerList; private PlayerSettingsManager mPlayerSettingsManager; private AudioManager mAudioManager; private AvrcpBroadcastReceiver mReceiver; private AvrcpNativeInterface mNativeInterface; private AvrcpVolumeManager mVolumeManager; private ServiceFactory mFactory = new ServiceFactory(); // Cover Art Service (Storage + BIP Server) private final AvrcpCoverArtService mAvrcpCoverArtService; private final AdapterService mAdapterService; private final AvrcpVersion mAvrcpVersion; private final MediaPlayerList mMediaPlayerList; private final PlayerSettingsManager mPlayerSettingsManager; private final AudioManager mAudioManager; private final AvrcpBroadcastReceiver mReceiver; private final AvrcpNativeInterface mNativeInterface; private final AvrcpVolumeManager mVolumeManager; private final ServiceFactory mFactory = new ServiceFactory(); private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() { @Override Loading @@ -84,24 +90,65 @@ public class AvrcpTargetService extends ProfileService { Log.e(TAG, "userChangeReceiver received an invalid EXTRA_USER_HANDLE"); return; } if (mMediaPlayerList != null) { mMediaPlayerList.init(new ListCallback()); } } }; // Only used to see if the metadata has changed from its previous value private MediaData mCurrentData; // Cover Art Service (Storage + BIP Server) private AvrcpCoverArtService mAvrcpCoverArtService = null; private static AvrcpTargetService sInstance = null; private final AdapterService mAdapterService; public AvrcpTargetService(AdapterService adapterService) { super(adapterService); super(requireNonNull(adapterService)); mAdapterService = adapterService; mAudioManager = requireNonNull(getSystemService(AudioManager.class)); mNativeInterface = requireNonNull(AvrcpNativeInterface.getInstance()); mMediaPlayerList = new MediaPlayerList(Looper.myLooper(), this); IntentFilter userFilter = new IntentFilter(); userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); userFilter.addAction(Intent.ACTION_USER_UNLOCKED); getApplicationContext().registerReceiver(mUserUnlockedReceiver, userFilter); Log.i(TAG, "Starting the AVRCP Target Service"); mCurrentData = new MediaData(null, null, null); mPlayerSettingsManager = new PlayerSettingsManager(mMediaPlayerList, this); mNativeInterface.init(this); mAvrcpVersion = AvrcpVersion.getCurrentSystemPropertiesValue(); mVolumeManager = new AvrcpVolumeManager(mAdapterService, mAudioManager, mNativeInterface); UserManager userManager = getApplicationContext().getSystemService(UserManager.class); if (userManager.isUserUnlocked()) { mMediaPlayerList.init(new ListCallback()); } if (!getResources().getBoolean(R.bool.avrcp_target_enable_cover_art)) { mAvrcpCoverArtService = null; } else if (!mAvrcpVersion.isAtleastVersion(AvrcpVersion.AVRCP_VERSION_1_6)) { Log.e(TAG, "Please use AVRCP version 1.6 to enable cover art"); mAvrcpCoverArtService = null; } else { AvrcpCoverArtService coverArtService = new AvrcpCoverArtService(); if (coverArtService.start()) { mAvrcpCoverArtService = coverArtService; } else { Log.e(TAG, "Failed to start cover art service"); mAvrcpCoverArtService = null; } } mReceiver = new AvrcpBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(AudioManager.ACTION_VOLUME_CHANGED); registerReceiver(mReceiver, filter); // Only allow the service to be used once it is initialized sInstance = this; } /** Checks for profile enabled state in Bluetooth sysprops. */ Loading @@ -113,8 +160,6 @@ public class AvrcpTargetService extends ProfileService { class ListCallback implements MediaPlayerList.MediaUpdateCallback { @Override public void run(MediaData data) { if (mNativeInterface == null) return; boolean metadata = !Objects.equals(mCurrentData.metadata, data.metadata); boolean state = !MediaPlayerWrapper.playstateEquals(mCurrentData.state, data.state); boolean queue = isQueueUpdated(mCurrentData.queue, data.queue); Loading @@ -134,8 +179,6 @@ public class AvrcpTargetService extends ProfileService { @Override public void run(boolean availablePlayers, boolean addressedPlayers, boolean uids) { if (mNativeInterface == null) return; mNativeInterface.sendFolderUpdate(availablePlayers, addressedPlayers, uids); } } Loading @@ -148,20 +191,21 @@ public class AvrcpTargetService extends ProfileService { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(AudioManager.ACTION_VOLUME_CHANGED)) { if (!action.equals(AudioManager.ACTION_VOLUME_CHANGED)) { return; } int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); if (streamType == AudioManager.STREAM_MUSIC) { if (streamType != AudioManager.STREAM_MUSIC) { return; } int volume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); BluetoothDevice activeDevice = getA2dpActiveDevice(); if (activeDevice != null && !mVolumeManager.getAbsoluteVolumeSupported(activeDevice)) { if (activeDevice != null && !mVolumeManager.getAbsoluteVolumeSupported(activeDevice)) { Log.d(TAG, "stream volume change to " + volume + " " + activeDevice); mVolumeManager.storeVolumeForDevice(activeDevice, volume); } } } } } /** Sets the AvrcpTargetService instance. */ @VisibleForTesting Loading Loading @@ -193,61 +237,6 @@ public class AvrcpTargetService extends ProfileService { return null; } @Override public void start() { if (sInstance != null) { throw new IllegalStateException("start() called twice"); } IntentFilter userFilter = new IntentFilter(); userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); userFilter.addAction(Intent.ACTION_USER_UNLOCKED); getApplicationContext().registerReceiver(mUserUnlockedReceiver, userFilter); Log.i(TAG, "Starting the AVRCP Target Service"); mCurrentData = new MediaData(null, null, null); mAudioManager = getSystemService(AudioManager.class); mMediaPlayerList = new MediaPlayerList(Looper.myLooper(), this); mPlayerSettingsManager = new PlayerSettingsManager(mMediaPlayerList, this); mNativeInterface = AvrcpNativeInterface.getInstance(); mNativeInterface.init(AvrcpTargetService.this); mAvrcpVersion = AvrcpVersion.getCurrentSystemPropertiesValue(); mVolumeManager = new AvrcpVolumeManager(mAdapterService, mAudioManager, mNativeInterface); UserManager userManager = getApplicationContext().getSystemService(UserManager.class); if (userManager.isUserUnlocked()) { mMediaPlayerList.init(new ListCallback()); } if (getResources().getBoolean(R.bool.avrcp_target_enable_cover_art)) { if (mAvrcpVersion.isAtleastVersion(AvrcpVersion.AVRCP_VERSION_1_6)) { mAvrcpCoverArtService = new AvrcpCoverArtService(); boolean started = mAvrcpCoverArtService.start(); if (!started) { Log.e(TAG, "Failed to start cover art service"); mAvrcpCoverArtService = null; } } else { Log.e(TAG, "Please use AVRCP version 1.6 to enable cover art"); } } mReceiver = new AvrcpBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(AudioManager.ACTION_VOLUME_CHANGED); registerReceiver(mReceiver, filter); // Only allow the service to be used once it is initialized sInstance = this; } @Override public void stop() { Log.i(TAG, "Stopping the AVRCP Target Service"); Loading @@ -260,22 +249,15 @@ public class AvrcpTargetService extends ProfileService { if (mAvrcpCoverArtService != null) { mAvrcpCoverArtService.stop(); } mAvrcpCoverArtService = null; sInstance = null; unregisterReceiver(mReceiver); // We check the interfaces first since they only get set on User Unlocked if (mPlayerSettingsManager != null) mPlayerSettingsManager.cleanup(); if (mMediaPlayerList != null) mMediaPlayerList.cleanup(); if (mNativeInterface != null) mNativeInterface.cleanup(); mPlayerSettingsManager.cleanup(); mMediaPlayerList.cleanup(); mNativeInterface.cleanup(); getApplicationContext().unregisterReceiver(mUserUnlockedReceiver); mPlayerSettingsManager = null; mMediaPlayerList = null; mNativeInterface = null; mAudioManager = null; mReceiver = null; } /** Returns the active A2DP {@link BluetoothDevice} */ Loading Loading @@ -339,7 +321,7 @@ public class AvrcpTargetService extends ProfileService { * <p>If the A2DP connection disconnects, we request AVRCP to disconnect device as well. */ public void handleA2dpConnectionStateChanged(BluetoothDevice device, int newState) { if (device == null || mNativeInterface == null) return; if (device == null) return; if (newState == BluetoothProfile.STATE_DISCONNECTED) { // If there is no connection, disconnectDevice() will do nothing if (mNativeInterface.disconnectDevice(device)) { Loading @@ -359,11 +341,9 @@ public class AvrcpTargetService extends ProfileService { */ public void handleA2dpActiveDeviceChanged(BluetoothDevice device) { mVolumeManager.volumeDeviceSwitched(device); if (mNativeInterface != null) { // Update all the playback status info for each connected device mNativeInterface.sendMediaUpdate(false, true, false); } } /** Informs {@link AvrcpVolumeManager} that a remote device requests a volume change */ void setVolume(int avrcpVolume) { Loading Loading @@ -575,11 +555,6 @@ public class AvrcpTargetService extends ProfileService { /** Called from player callback to indicate new settings to remote device. */ public void sendPlayerSettings(int repeatMode, int shuffleMode) { if (mNativeInterface == null) { Log.i(TAG, "Tried to send Player Settings while native interface is null"); return; } mNativeInterface.sendPlayerSettings(repeatMode, shuffleMode); } Loading Loading @@ -626,11 +601,7 @@ public class AvrcpTargetService extends ProfileService { StringBuilder tempBuilder = new StringBuilder(); tempBuilder.append("AVRCP version: ").append(mAvrcpVersion).append("\n"); if (mMediaPlayerList != null) { mMediaPlayerList.dump(tempBuilder); } else { tempBuilder.append("\nMedia Player List is empty\n"); } mMediaKeyEventLogger.dump(tempBuilder); tempBuilder.append("\n"); Loading Loading
android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java +82 −111 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.bluetooth.avrcp; import static java.util.Objects.requireNonNull; import android.annotation.NonNull; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; Loading Loading @@ -62,14 +64,18 @@ public class AvrcpTargetService extends ProfileService { private final BluetoothEventLogger mMediaKeyEventLogger = new BluetoothEventLogger(MEDIA_KEY_EVENT_LOGGER_SIZE, MEDIA_KEY_EVENT_LOGGER_TITLE); private AvrcpVersion mAvrcpVersion; private MediaPlayerList mMediaPlayerList; private PlayerSettingsManager mPlayerSettingsManager; private AudioManager mAudioManager; private AvrcpBroadcastReceiver mReceiver; private AvrcpNativeInterface mNativeInterface; private AvrcpVolumeManager mVolumeManager; private ServiceFactory mFactory = new ServiceFactory(); // Cover Art Service (Storage + BIP Server) private final AvrcpCoverArtService mAvrcpCoverArtService; private final AdapterService mAdapterService; private final AvrcpVersion mAvrcpVersion; private final MediaPlayerList mMediaPlayerList; private final PlayerSettingsManager mPlayerSettingsManager; private final AudioManager mAudioManager; private final AvrcpBroadcastReceiver mReceiver; private final AvrcpNativeInterface mNativeInterface; private final AvrcpVolumeManager mVolumeManager; private final ServiceFactory mFactory = new ServiceFactory(); private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() { @Override Loading @@ -84,24 +90,65 @@ public class AvrcpTargetService extends ProfileService { Log.e(TAG, "userChangeReceiver received an invalid EXTRA_USER_HANDLE"); return; } if (mMediaPlayerList != null) { mMediaPlayerList.init(new ListCallback()); } } }; // Only used to see if the metadata has changed from its previous value private MediaData mCurrentData; // Cover Art Service (Storage + BIP Server) private AvrcpCoverArtService mAvrcpCoverArtService = null; private static AvrcpTargetService sInstance = null; private final AdapterService mAdapterService; public AvrcpTargetService(AdapterService adapterService) { super(adapterService); super(requireNonNull(adapterService)); mAdapterService = adapterService; mAudioManager = requireNonNull(getSystemService(AudioManager.class)); mNativeInterface = requireNonNull(AvrcpNativeInterface.getInstance()); mMediaPlayerList = new MediaPlayerList(Looper.myLooper(), this); IntentFilter userFilter = new IntentFilter(); userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); userFilter.addAction(Intent.ACTION_USER_UNLOCKED); getApplicationContext().registerReceiver(mUserUnlockedReceiver, userFilter); Log.i(TAG, "Starting the AVRCP Target Service"); mCurrentData = new MediaData(null, null, null); mPlayerSettingsManager = new PlayerSettingsManager(mMediaPlayerList, this); mNativeInterface.init(this); mAvrcpVersion = AvrcpVersion.getCurrentSystemPropertiesValue(); mVolumeManager = new AvrcpVolumeManager(mAdapterService, mAudioManager, mNativeInterface); UserManager userManager = getApplicationContext().getSystemService(UserManager.class); if (userManager.isUserUnlocked()) { mMediaPlayerList.init(new ListCallback()); } if (!getResources().getBoolean(R.bool.avrcp_target_enable_cover_art)) { mAvrcpCoverArtService = null; } else if (!mAvrcpVersion.isAtleastVersion(AvrcpVersion.AVRCP_VERSION_1_6)) { Log.e(TAG, "Please use AVRCP version 1.6 to enable cover art"); mAvrcpCoverArtService = null; } else { AvrcpCoverArtService coverArtService = new AvrcpCoverArtService(); if (coverArtService.start()) { mAvrcpCoverArtService = coverArtService; } else { Log.e(TAG, "Failed to start cover art service"); mAvrcpCoverArtService = null; } } mReceiver = new AvrcpBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(AudioManager.ACTION_VOLUME_CHANGED); registerReceiver(mReceiver, filter); // Only allow the service to be used once it is initialized sInstance = this; } /** Checks for profile enabled state in Bluetooth sysprops. */ Loading @@ -113,8 +160,6 @@ public class AvrcpTargetService extends ProfileService { class ListCallback implements MediaPlayerList.MediaUpdateCallback { @Override public void run(MediaData data) { if (mNativeInterface == null) return; boolean metadata = !Objects.equals(mCurrentData.metadata, data.metadata); boolean state = !MediaPlayerWrapper.playstateEquals(mCurrentData.state, data.state); boolean queue = isQueueUpdated(mCurrentData.queue, data.queue); Loading @@ -134,8 +179,6 @@ public class AvrcpTargetService extends ProfileService { @Override public void run(boolean availablePlayers, boolean addressedPlayers, boolean uids) { if (mNativeInterface == null) return; mNativeInterface.sendFolderUpdate(availablePlayers, addressedPlayers, uids); } } Loading @@ -148,20 +191,21 @@ public class AvrcpTargetService extends ProfileService { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(AudioManager.ACTION_VOLUME_CHANGED)) { if (!action.equals(AudioManager.ACTION_VOLUME_CHANGED)) { return; } int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); if (streamType == AudioManager.STREAM_MUSIC) { if (streamType != AudioManager.STREAM_MUSIC) { return; } int volume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); BluetoothDevice activeDevice = getA2dpActiveDevice(); if (activeDevice != null && !mVolumeManager.getAbsoluteVolumeSupported(activeDevice)) { if (activeDevice != null && !mVolumeManager.getAbsoluteVolumeSupported(activeDevice)) { Log.d(TAG, "stream volume change to " + volume + " " + activeDevice); mVolumeManager.storeVolumeForDevice(activeDevice, volume); } } } } } /** Sets the AvrcpTargetService instance. */ @VisibleForTesting Loading Loading @@ -193,61 +237,6 @@ public class AvrcpTargetService extends ProfileService { return null; } @Override public void start() { if (sInstance != null) { throw new IllegalStateException("start() called twice"); } IntentFilter userFilter = new IntentFilter(); userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); userFilter.addAction(Intent.ACTION_USER_UNLOCKED); getApplicationContext().registerReceiver(mUserUnlockedReceiver, userFilter); Log.i(TAG, "Starting the AVRCP Target Service"); mCurrentData = new MediaData(null, null, null); mAudioManager = getSystemService(AudioManager.class); mMediaPlayerList = new MediaPlayerList(Looper.myLooper(), this); mPlayerSettingsManager = new PlayerSettingsManager(mMediaPlayerList, this); mNativeInterface = AvrcpNativeInterface.getInstance(); mNativeInterface.init(AvrcpTargetService.this); mAvrcpVersion = AvrcpVersion.getCurrentSystemPropertiesValue(); mVolumeManager = new AvrcpVolumeManager(mAdapterService, mAudioManager, mNativeInterface); UserManager userManager = getApplicationContext().getSystemService(UserManager.class); if (userManager.isUserUnlocked()) { mMediaPlayerList.init(new ListCallback()); } if (getResources().getBoolean(R.bool.avrcp_target_enable_cover_art)) { if (mAvrcpVersion.isAtleastVersion(AvrcpVersion.AVRCP_VERSION_1_6)) { mAvrcpCoverArtService = new AvrcpCoverArtService(); boolean started = mAvrcpCoverArtService.start(); if (!started) { Log.e(TAG, "Failed to start cover art service"); mAvrcpCoverArtService = null; } } else { Log.e(TAG, "Please use AVRCP version 1.6 to enable cover art"); } } mReceiver = new AvrcpBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(AudioManager.ACTION_VOLUME_CHANGED); registerReceiver(mReceiver, filter); // Only allow the service to be used once it is initialized sInstance = this; } @Override public void stop() { Log.i(TAG, "Stopping the AVRCP Target Service"); Loading @@ -260,22 +249,15 @@ public class AvrcpTargetService extends ProfileService { if (mAvrcpCoverArtService != null) { mAvrcpCoverArtService.stop(); } mAvrcpCoverArtService = null; sInstance = null; unregisterReceiver(mReceiver); // We check the interfaces first since they only get set on User Unlocked if (mPlayerSettingsManager != null) mPlayerSettingsManager.cleanup(); if (mMediaPlayerList != null) mMediaPlayerList.cleanup(); if (mNativeInterface != null) mNativeInterface.cleanup(); mPlayerSettingsManager.cleanup(); mMediaPlayerList.cleanup(); mNativeInterface.cleanup(); getApplicationContext().unregisterReceiver(mUserUnlockedReceiver); mPlayerSettingsManager = null; mMediaPlayerList = null; mNativeInterface = null; mAudioManager = null; mReceiver = null; } /** Returns the active A2DP {@link BluetoothDevice} */ Loading Loading @@ -339,7 +321,7 @@ public class AvrcpTargetService extends ProfileService { * <p>If the A2DP connection disconnects, we request AVRCP to disconnect device as well. */ public void handleA2dpConnectionStateChanged(BluetoothDevice device, int newState) { if (device == null || mNativeInterface == null) return; if (device == null) return; if (newState == BluetoothProfile.STATE_DISCONNECTED) { // If there is no connection, disconnectDevice() will do nothing if (mNativeInterface.disconnectDevice(device)) { Loading @@ -359,11 +341,9 @@ public class AvrcpTargetService extends ProfileService { */ public void handleA2dpActiveDeviceChanged(BluetoothDevice device) { mVolumeManager.volumeDeviceSwitched(device); if (mNativeInterface != null) { // Update all the playback status info for each connected device mNativeInterface.sendMediaUpdate(false, true, false); } } /** Informs {@link AvrcpVolumeManager} that a remote device requests a volume change */ void setVolume(int avrcpVolume) { Loading Loading @@ -575,11 +555,6 @@ public class AvrcpTargetService extends ProfileService { /** Called from player callback to indicate new settings to remote device. */ public void sendPlayerSettings(int repeatMode, int shuffleMode) { if (mNativeInterface == null) { Log.i(TAG, "Tried to send Player Settings while native interface is null"); return; } mNativeInterface.sendPlayerSettings(repeatMode, shuffleMode); } Loading Loading @@ -626,11 +601,7 @@ public class AvrcpTargetService extends ProfileService { StringBuilder tempBuilder = new StringBuilder(); tempBuilder.append("AVRCP version: ").append(mAvrcpVersion).append("\n"); if (mMediaPlayerList != null) { mMediaPlayerList.dump(tempBuilder); } else { tempBuilder.append("\nMedia Player List is empty\n"); } mMediaKeyEventLogger.dump(tempBuilder); tempBuilder.append("\n"); Loading