Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java +157 −77 Original line number Diff line number Diff line Loading @@ -16,29 +16,47 @@ package com.android.settingslib.bluetooth; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile.ServiceListener; import android.content.Context; import android.os.Build; import android.util.Log; import androidx.annotation.RequiresApi; import com.android.settingslib.R; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; /** * LocalBluetoothLeBroadcast provides an interface between the Settings app * and the functionality of the local {@link BluetoothLeBroadcast}. * Use the {@link BluetoothLeBroadcast.Callback} to get the result callback. */ public class LocalBluetoothLeBroadcast implements BluetoothLeBroadcast.Callback { public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { private static final String TAG = "LocalBluetoothLeBroadcast"; private static final int UNKNOWN_VALUE_PLACEHOLDER = -1; private static final boolean DEBUG = BluetoothUtils.D; private BluetoothLeBroadcast mBluetoothLeBroadcast; private LocalBluetoothProfileManager mProfileManager; static final String NAME = "LE_AUDIO_BROADCAST"; // Order of this profile in device profiles list private static final int ORDINAL = 1; private BluetoothLeBroadcast mService; private BluetoothLeAudioContentMetadata mBluetoothLeAudioContentMetadata; private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata; private BluetoothLeAudioContentMetadata.Builder mBuilder; Loading @@ -48,29 +66,31 @@ public class LocalBluetoothLeBroadcast implements BluetoothLeBroadcast.Callback private final ServiceListener mServiceListener = new ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) { if (profile != BluetoothProfile.LE_AUDIO_BROADCAST) { Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST"); return; } if (DEBUG) { Log.d(TAG, "Bluetooth service connected"); } mBluetoothLeBroadcast = (BluetoothLeBroadcast) proxy; mProfileManager.callServiceConnectedListeners(); mService = (BluetoothLeBroadcast) proxy; mIsProfileReady = true; } } @Override public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) { if (profile != BluetoothProfile.LE_AUDIO_BROADCAST) { Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST"); return; } if (DEBUG) { Log.d(TAG, "Bluetooth service disconnected"); } mIsProfileReady = false; } } }; LocalBluetoothLeBroadcast(Context context, LocalBluetoothProfileManager profileManager) { mProfileManager = profileManager; LocalBluetoothLeBroadcast(Context context) { BluetoothAdapter.getDefaultAdapter(). getProfileProxy(context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST); mBuilder = new BluetoothLeAudioContentMetadata.Builder(); Loading @@ -78,39 +98,58 @@ public class LocalBluetoothLeBroadcast implements BluetoothLeBroadcast.Callback public void startBroadcast(byte[] broadcastCode, String language, String programInfo) { if (DEBUG) { if (mBluetoothLeBroadcast == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null when starting the broadcast."); return; } if (DEBUG) { Log.d(TAG, "startBroadcast: language = " + language + " ,programInfo = " + programInfo); } buildContentMetadata(language, programInfo); mBluetoothLeBroadcast.startBroadcast(mBluetoothLeAudioContentMetadata, broadcastCode); mService.startBroadcast(mBluetoothLeAudioContentMetadata, broadcastCode); } public void stopBroadcast() { if (DEBUG) { if (mBluetoothLeBroadcast == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null when stopping the broadcast."); return; } if (DEBUG) { Log.d(TAG, "stopBroadcast()"); } mBluetoothLeBroadcast.stopBroadcast(mBroadcastId); mService.stopBroadcast(mBroadcastId); } public void updateBroadcast(String language, String programInfo) { if (DEBUG) { if (mBluetoothLeBroadcast == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null when updating the broadcast."); return; } if (DEBUG) { Log.d(TAG, "updateBroadcast: language = " + language + " ,programInfo = " + programInfo); } mBluetoothLeAudioContentMetadata = mBuilder.setProgramInfo(programInfo).build(); mBluetoothLeBroadcast.updateBroadcast(mBroadcastId, mBluetoothLeAudioContentMetadata); mService.updateBroadcast(mBroadcastId, mBluetoothLeAudioContentMetadata); } public void registerServiceCallBack(@NonNull @CallbackExecutor Executor executor, @NonNull BluetoothLeBroadcast.Callback callback) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return; } mService.registerCallback(executor, callback); } public void unregisterServiceCallBack(@NonNull BluetoothLeBroadcast.Callback callback) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return; } mService.unregisterCallback(callback); } private void buildContentMetadata(String language, String programInfo) { Loading @@ -122,71 +161,112 @@ public class LocalBluetoothLeBroadcast implements BluetoothLeBroadcast.Callback return new LocalBluetoothLeBroadcastMetadata(mBluetoothLeBroadcastMetadata); } public boolean isProfileReady() { return mIsProfileReady; } @Override public void onBroadcastStarted(int reason, int broadcastId) { if (DEBUG) { Log.d(TAG, "onBroadcastStarted(), reason = " + reason + ", broadcastId = " + broadcastId); public int getProfileId() { return BluetoothProfile.LE_AUDIO_BROADCAST; } public boolean accessProfileEnabled() { return false; } @Override public void onBroadcastStartFailed(int reason) { if (DEBUG) { Log.d(TAG, "onBroadcastStartFailed(), reason = " + reason); public boolean isAutoConnectable() { return true; } /** * Not supported since LE Audio Broadcasts do not establish a connection. */ public int getConnectionStatus(BluetoothDevice device) { if (mService == null) { return BluetoothProfile.STATE_DISCONNECTED; } // LE Audio Broadcasts are not connection-oriented. return mService.getConnectionState(device); } @Override public void onBroadcastMetadataChanged(int broadcastId, @NonNull BluetoothLeBroadcastMetadata metadata) { if (DEBUG) { Log.d(TAG, "onBroadcastMetadataChanged(), broadcastId = " + broadcastId); /** * Not supported since LE Audio Broadcasts do not establish a connection. */ public List<BluetoothDevice> getConnectedDevices() { if (mService == null) { return new ArrayList<BluetoothDevice>(0); } mBluetoothLeBroadcastMetadata = metadata; // LE Audio Broadcasts are not connection-oriented. return mService.getConnectedDevices(); } @Override public void onBroadcastStopped(int reason, int broadcastId) { if (DEBUG) { Log.d(TAG, "onBroadcastStopped(), reason = " + reason + ", broadcastId = " + broadcastId); public @NonNull List<BluetoothLeBroadcastMetadata> getAllBroadcastMetadata() { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return Collections.emptyList(); } return mService.getAllBroadcastMetadata(); } @Override public void onBroadcastStopFailed(int reason) { if (DEBUG) { Log.d(TAG, "onBroadcastStopFailed(), reason = " + reason); public boolean isEnabled(BluetoothDevice device) { if (mService == null) { return false; } return !mService.getAllBroadcastMetadata().isEmpty(); } @Override public void onBroadcastUpdated(int reason, int broadcastId) { if (DEBUG) { Log.d(TAG, "onBroadcastUpdated(), reason = " + reason + ", broadcastId = " + broadcastId); /** * Service does not provide method to get/set policy. */ public int getConnectionPolicy(BluetoothDevice device) { return CONNECTION_POLICY_FORBIDDEN; } /** * Service does not provide "setEnabled" method. Please use {@link #startBroadcast}, * {@link #stopBroadcast()} or {@link #updateBroadcast(String, String)} */ public boolean setEnabled(BluetoothDevice device, boolean enabled) { return false; } @Override public void onBroadcastUpdateFailed(int reason, int broadcastId) { if (DEBUG) { Log.d(TAG, "onBroadcastUpdateFailed(), reason = " + reason + ", broadcastId = " + broadcastId); public String toString() { return NAME; } public int getOrdinal() { return ORDINAL; } @Override public void onPlaybackStarted(int reason, int broadcastId) { public int getNameResource(BluetoothDevice device) { return R.string.summary_empty; } @Override public void onPlaybackStopped(int reason, int broadcastId) { public int getSummaryResourceForDevice(BluetoothDevice device) { int state = getConnectionStatus(device); return BluetoothUtils.getConnectionStateSummary(state); } public boolean isProfileReady() { return mIsProfileReady; public int getDrawableResource(BluetoothClass btClass) { return 0; } @RequiresApi(Build.VERSION_CODES.S) protected void finalize() { if (DEBUG) { Log.d(TAG, "finalize()"); } if (mService != null) { try { BluetoothAdapter.getDefaultAdapter().closeProfileProxy( BluetoothProfile.LE_AUDIO_BROADCAST, mService); mService = null; } catch (Throwable t) { Log.w(TAG, "Error cleaning up LeAudio proxy", t); } } } } packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java +156 −73 Original line number Diff line number Diff line Loading @@ -16,32 +16,48 @@ package com.android.settingslib.bluetooth; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile.ServiceListener; import android.content.Context; import android.os.Build; import android.util.Log; import androidx.annotation.RequiresApi; import com.android.settingslib.R; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; /** * LocalBluetoothLeBroadcastAssistant provides an interface between the Settings app * and the functionality of the local {@link BluetoothLeBroadcastAssistant}. * Use the {@link BluetoothLeBroadcastAssistant.Callback} to get the result callback. */ public class LocalBluetoothLeBroadcastAssistant implements BluetoothLeBroadcastAssistant.Callback { public class LocalBluetoothLeBroadcastAssistant implements LocalBluetoothProfile { private static final String TAG = "LocalBluetoothLeBroadcastAssistant"; private static final int UNKNOWN_VALUE_PLACEHOLDER = -1; private static final boolean DEBUG = BluetoothUtils.D; static final String NAME = "LE_AUDIO_BROADCAST_ASSISTANT"; // Order of this profile in device profiles list private static final int ORDINAL = 1; private LocalBluetoothProfileManager mProfileManager; private BluetoothLeBroadcastAssistant mBluetoothLeBroadcastAssistant; private BluetoothLeBroadcastAssistant mService; private final CachedBluetoothDeviceManager mDeviceManager; private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata; private BluetoothLeBroadcastMetadata.Builder mBuilder; private boolean mIsProfileReady; Loading @@ -49,30 +65,55 @@ public class LocalBluetoothLeBroadcastAssistant implements private final ServiceListener mServiceListener = new ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) { if (profile != BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) { Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST_ASSISTANT"); return; } if (DEBUG) { Log.d(TAG, "Bluetooth service connected"); } mBluetoothLeBroadcastAssistant = (BluetoothLeBroadcastAssistant) proxy; mService = (BluetoothLeBroadcastAssistant) proxy; // We just bound to the service, so refresh the UI for any connected LeAudio devices. List<BluetoothDevice> deviceList = mService.getConnectedDevices(); while (!deviceList.isEmpty()) { BluetoothDevice nextDevice = deviceList.remove(0); CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice); // we may add a new device here, but generally this should not happen if (device == null) { if (DEBUG) { Log.d(TAG, "LocalBluetoothLeBroadcastAssistant found new device: " + nextDevice); } device = mDeviceManager.addDevice(nextDevice); } device.onProfileStateChanged(LocalBluetoothLeBroadcastAssistant.this, BluetoothProfile.STATE_CONNECTED); device.refresh(); } mProfileManager.callServiceConnectedListeners(); mIsProfileReady = true; } } @Override public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) { if (profile != BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) { Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST_ASSISTANT"); return; } if (DEBUG) { Log.d(TAG, "Bluetooth service disconnected"); } mProfileManager.callServiceDisconnectedListeners(); mIsProfileReady = false; } } }; public LocalBluetoothLeBroadcastAssistant(Context context, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { mProfileManager = profileManager; mDeviceManager = deviceManager; BluetoothAdapter.getDefaultAdapter(). getProfileProxy(context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); Loading @@ -90,7 +131,11 @@ public class LocalBluetoothLeBroadcastAssistant implements */ public void addSource(BluetoothDevice sink, BluetoothLeBroadcastMetadata metadata, boolean isGroupOp) { mBluetoothLeBroadcastAssistant.addSource(sink, metadata, isGroupOp); if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return; } mService.addSource(sink, metadata, isGroupOp); } /** Loading Loading @@ -120,13 +165,9 @@ public class LocalBluetoothLeBroadcastAssistant implements if (DEBUG) { Log.d(TAG, "addSource()"); } if (mBluetoothLeBroadcastAssistant == null) { Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return ; } buildMetadata(sourceAddressType, presentationDelayMicros, sourceAdvertisingSid, broadcastId, paSyncInterval, isEncrypted, broadcastCode, sourceDevice); mBluetoothLeBroadcastAssistant.addSource(sink, mBluetoothLeBroadcastMetadata, isGroupOp); addSource(sink, mBluetoothLeBroadcastMetadata, isGroupOp); } private void buildMetadata(int sourceAddressType, int presentationDelayMicros, Loading @@ -147,101 +188,143 @@ public class LocalBluetoothLeBroadcastAssistant implements if (DEBUG) { Log.d(TAG, "removeSource()"); } if (mBluetoothLeBroadcastAssistant == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return; } mBluetoothLeBroadcastAssistant.removeSource(sink, sourceId); mService.removeSource(sink, sourceId); } public void startSearchingForSources(@NonNull List<android.bluetooth.le.ScanFilter> filters) { if (DEBUG) { Log.d(TAG, "startSearchingForSources()"); } if (mBluetoothLeBroadcastAssistant == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return; } mBluetoothLeBroadcastAssistant.startSearchingForSources(filters); mService.startSearchingForSources(filters); } @Override public void onSourceAdded(@NonNull BluetoothDevice sink, int sourceId, int reason) { if (DEBUG) { Log.d(TAG, "onSourceAdded(), reason = " + reason + " , sourceId = " + sourceId); public void registerServiceCallBack(@NonNull @CallbackExecutor Executor executor, @NonNull BluetoothLeBroadcastAssistant.Callback callback) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return; } mService.registerCallback(executor, callback); } @Override public void onSourceAddFailed(@NonNull BluetoothDevice sink, @NonNull BluetoothLeBroadcastMetadata source, int reason) { if (DEBUG) { Log.d(TAG, "onSourceAddFailed(), reason = " + reason); public void unregisterServiceCallBack( @NonNull BluetoothLeBroadcastAssistant.Callback callback) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return; } mService.unregisterCallback(callback); } @Override public void onSourceRemoved(@NonNull BluetoothDevice sink, int sourceId, int reason) { if (DEBUG) { Log.d(TAG, "onSourceRemoved(), reason = " + reason + " , sourceId = " + sourceId); public boolean isProfileReady() { return mIsProfileReady; } public int getProfileId() { return BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT; } @Override public void onSourceRemoveFailed(@NonNull BluetoothDevice sink, int sourceId, int reason) { if (DEBUG) { Log.d(TAG, "onSourceRemoveFailed(), reason = " + reason + " , sourceId = " + sourceId); public boolean accessProfileEnabled() { return false; } public boolean isAutoConnectable() { return true; } @Override public void onSearchStarted(int reason) { if (DEBUG) { Log.d(TAG, "onSearchStarted(), reason = " + reason); public int getConnectionStatus(BluetoothDevice device) { if (mService == null) { return BluetoothProfile.STATE_DISCONNECTED; } // LE Audio Broadcasts are not connection-oriented. return mService.getConnectionState(device); } @Override public void onSearchStartFailed(int reason) { if (DEBUG) { Log.d(TAG, "onSearchStartFailed(), reason = " + reason); public List<BluetoothDevice> getConnectedDevices() { if (mService == null) { return new ArrayList<BluetoothDevice>(0); } return mService.getDevicesMatchingConnectionStates( new int[]{BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTING}); } @Override public void onSearchStopped(int reason) { if (DEBUG) { Log.d(TAG, "onSearchStopped(), reason = " + reason); public boolean isEnabled(BluetoothDevice device) { if (mService == null || device == null) { return false; } return mService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN; } @Override public void onSearchStopFailed(int reason) { if (DEBUG) { Log.d(TAG, "onSearchStopFailed(), reason = " + reason); public int getConnectionPolicy(BluetoothDevice device) { if (mService == null || device == null) { return CONNECTION_POLICY_FORBIDDEN; } return mService.getConnectionPolicy(device); } @Override public void onSourceFound(@NonNull BluetoothLeBroadcastMetadata source) { public boolean setEnabled(BluetoothDevice device, boolean enabled) { boolean isEnabled = false; if (mService == null || device == null) { return false; } if (enabled) { if (mService.getConnectionPolicy(device) < CONNECTION_POLICY_ALLOWED) { isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); } } else { isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_FORBIDDEN); } @Override public void onSourceModified(@NonNull BluetoothDevice sink, int sourceId, int reason) { return isEnabled; } @Override public void onSourceModifyFailed(@NonNull BluetoothDevice sink, int sourceId, int reason) { public String toString() { return NAME; } @Override public void onReceiveStateChanged(@NonNull BluetoothDevice sink, int sourceId, @NonNull BluetoothLeBroadcastReceiveState state) { public int getOrdinal() { return ORDINAL; } public boolean isProfileReady() { return mIsProfileReady; public int getNameResource(BluetoothDevice device) { return R.string.summary_empty; } public int getSummaryResourceForDevice(BluetoothDevice device) { int state = getConnectionStatus(device); return BluetoothUtils.getConnectionStateSummary(state); } public int getDrawableResource(BluetoothClass btClass) { return 0; } @RequiresApi(Build.VERSION_CODES.S) protected void finalize() { if (DEBUG) { Log.d(TAG, "finalize()"); } if (mService != null) { try { BluetoothAdapter.getDefaultAdapter().closeProfileProxy( BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, mService); mService = null; } catch (Throwable t) { Log.w(TAG, "Error cleaning up LeAudio proxy", t); } } } } packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +30 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java +157 −77 Original line number Diff line number Diff line Loading @@ -16,29 +16,47 @@ package com.android.settingslib.bluetooth; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile.ServiceListener; import android.content.Context; import android.os.Build; import android.util.Log; import androidx.annotation.RequiresApi; import com.android.settingslib.R; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; /** * LocalBluetoothLeBroadcast provides an interface between the Settings app * and the functionality of the local {@link BluetoothLeBroadcast}. * Use the {@link BluetoothLeBroadcast.Callback} to get the result callback. */ public class LocalBluetoothLeBroadcast implements BluetoothLeBroadcast.Callback { public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { private static final String TAG = "LocalBluetoothLeBroadcast"; private static final int UNKNOWN_VALUE_PLACEHOLDER = -1; private static final boolean DEBUG = BluetoothUtils.D; private BluetoothLeBroadcast mBluetoothLeBroadcast; private LocalBluetoothProfileManager mProfileManager; static final String NAME = "LE_AUDIO_BROADCAST"; // Order of this profile in device profiles list private static final int ORDINAL = 1; private BluetoothLeBroadcast mService; private BluetoothLeAudioContentMetadata mBluetoothLeAudioContentMetadata; private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata; private BluetoothLeAudioContentMetadata.Builder mBuilder; Loading @@ -48,29 +66,31 @@ public class LocalBluetoothLeBroadcast implements BluetoothLeBroadcast.Callback private final ServiceListener mServiceListener = new ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) { if (profile != BluetoothProfile.LE_AUDIO_BROADCAST) { Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST"); return; } if (DEBUG) { Log.d(TAG, "Bluetooth service connected"); } mBluetoothLeBroadcast = (BluetoothLeBroadcast) proxy; mProfileManager.callServiceConnectedListeners(); mService = (BluetoothLeBroadcast) proxy; mIsProfileReady = true; } } @Override public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) { if (profile != BluetoothProfile.LE_AUDIO_BROADCAST) { Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST"); return; } if (DEBUG) { Log.d(TAG, "Bluetooth service disconnected"); } mIsProfileReady = false; } } }; LocalBluetoothLeBroadcast(Context context, LocalBluetoothProfileManager profileManager) { mProfileManager = profileManager; LocalBluetoothLeBroadcast(Context context) { BluetoothAdapter.getDefaultAdapter(). getProfileProxy(context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST); mBuilder = new BluetoothLeAudioContentMetadata.Builder(); Loading @@ -78,39 +98,58 @@ public class LocalBluetoothLeBroadcast implements BluetoothLeBroadcast.Callback public void startBroadcast(byte[] broadcastCode, String language, String programInfo) { if (DEBUG) { if (mBluetoothLeBroadcast == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null when starting the broadcast."); return; } if (DEBUG) { Log.d(TAG, "startBroadcast: language = " + language + " ,programInfo = " + programInfo); } buildContentMetadata(language, programInfo); mBluetoothLeBroadcast.startBroadcast(mBluetoothLeAudioContentMetadata, broadcastCode); mService.startBroadcast(mBluetoothLeAudioContentMetadata, broadcastCode); } public void stopBroadcast() { if (DEBUG) { if (mBluetoothLeBroadcast == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null when stopping the broadcast."); return; } if (DEBUG) { Log.d(TAG, "stopBroadcast()"); } mBluetoothLeBroadcast.stopBroadcast(mBroadcastId); mService.stopBroadcast(mBroadcastId); } public void updateBroadcast(String language, String programInfo) { if (DEBUG) { if (mBluetoothLeBroadcast == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null when updating the broadcast."); return; } if (DEBUG) { Log.d(TAG, "updateBroadcast: language = " + language + " ,programInfo = " + programInfo); } mBluetoothLeAudioContentMetadata = mBuilder.setProgramInfo(programInfo).build(); mBluetoothLeBroadcast.updateBroadcast(mBroadcastId, mBluetoothLeAudioContentMetadata); mService.updateBroadcast(mBroadcastId, mBluetoothLeAudioContentMetadata); } public void registerServiceCallBack(@NonNull @CallbackExecutor Executor executor, @NonNull BluetoothLeBroadcast.Callback callback) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return; } mService.registerCallback(executor, callback); } public void unregisterServiceCallBack(@NonNull BluetoothLeBroadcast.Callback callback) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return; } mService.unregisterCallback(callback); } private void buildContentMetadata(String language, String programInfo) { Loading @@ -122,71 +161,112 @@ public class LocalBluetoothLeBroadcast implements BluetoothLeBroadcast.Callback return new LocalBluetoothLeBroadcastMetadata(mBluetoothLeBroadcastMetadata); } public boolean isProfileReady() { return mIsProfileReady; } @Override public void onBroadcastStarted(int reason, int broadcastId) { if (DEBUG) { Log.d(TAG, "onBroadcastStarted(), reason = " + reason + ", broadcastId = " + broadcastId); public int getProfileId() { return BluetoothProfile.LE_AUDIO_BROADCAST; } public boolean accessProfileEnabled() { return false; } @Override public void onBroadcastStartFailed(int reason) { if (DEBUG) { Log.d(TAG, "onBroadcastStartFailed(), reason = " + reason); public boolean isAutoConnectable() { return true; } /** * Not supported since LE Audio Broadcasts do not establish a connection. */ public int getConnectionStatus(BluetoothDevice device) { if (mService == null) { return BluetoothProfile.STATE_DISCONNECTED; } // LE Audio Broadcasts are not connection-oriented. return mService.getConnectionState(device); } @Override public void onBroadcastMetadataChanged(int broadcastId, @NonNull BluetoothLeBroadcastMetadata metadata) { if (DEBUG) { Log.d(TAG, "onBroadcastMetadataChanged(), broadcastId = " + broadcastId); /** * Not supported since LE Audio Broadcasts do not establish a connection. */ public List<BluetoothDevice> getConnectedDevices() { if (mService == null) { return new ArrayList<BluetoothDevice>(0); } mBluetoothLeBroadcastMetadata = metadata; // LE Audio Broadcasts are not connection-oriented. return mService.getConnectedDevices(); } @Override public void onBroadcastStopped(int reason, int broadcastId) { if (DEBUG) { Log.d(TAG, "onBroadcastStopped(), reason = " + reason + ", broadcastId = " + broadcastId); public @NonNull List<BluetoothLeBroadcastMetadata> getAllBroadcastMetadata() { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return Collections.emptyList(); } return mService.getAllBroadcastMetadata(); } @Override public void onBroadcastStopFailed(int reason) { if (DEBUG) { Log.d(TAG, "onBroadcastStopFailed(), reason = " + reason); public boolean isEnabled(BluetoothDevice device) { if (mService == null) { return false; } return !mService.getAllBroadcastMetadata().isEmpty(); } @Override public void onBroadcastUpdated(int reason, int broadcastId) { if (DEBUG) { Log.d(TAG, "onBroadcastUpdated(), reason = " + reason + ", broadcastId = " + broadcastId); /** * Service does not provide method to get/set policy. */ public int getConnectionPolicy(BluetoothDevice device) { return CONNECTION_POLICY_FORBIDDEN; } /** * Service does not provide "setEnabled" method. Please use {@link #startBroadcast}, * {@link #stopBroadcast()} or {@link #updateBroadcast(String, String)} */ public boolean setEnabled(BluetoothDevice device, boolean enabled) { return false; } @Override public void onBroadcastUpdateFailed(int reason, int broadcastId) { if (DEBUG) { Log.d(TAG, "onBroadcastUpdateFailed(), reason = " + reason + ", broadcastId = " + broadcastId); public String toString() { return NAME; } public int getOrdinal() { return ORDINAL; } @Override public void onPlaybackStarted(int reason, int broadcastId) { public int getNameResource(BluetoothDevice device) { return R.string.summary_empty; } @Override public void onPlaybackStopped(int reason, int broadcastId) { public int getSummaryResourceForDevice(BluetoothDevice device) { int state = getConnectionStatus(device); return BluetoothUtils.getConnectionStateSummary(state); } public boolean isProfileReady() { return mIsProfileReady; public int getDrawableResource(BluetoothClass btClass) { return 0; } @RequiresApi(Build.VERSION_CODES.S) protected void finalize() { if (DEBUG) { Log.d(TAG, "finalize()"); } if (mService != null) { try { BluetoothAdapter.getDefaultAdapter().closeProfileProxy( BluetoothProfile.LE_AUDIO_BROADCAST, mService); mService = null; } catch (Throwable t) { Log.w(TAG, "Error cleaning up LeAudio proxy", t); } } } }
packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java +156 −73 Original line number Diff line number Diff line Loading @@ -16,32 +16,48 @@ package com.android.settingslib.bluetooth; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastReceiveState; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile.ServiceListener; import android.content.Context; import android.os.Build; import android.util.Log; import androidx.annotation.RequiresApi; import com.android.settingslib.R; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; /** * LocalBluetoothLeBroadcastAssistant provides an interface between the Settings app * and the functionality of the local {@link BluetoothLeBroadcastAssistant}. * Use the {@link BluetoothLeBroadcastAssistant.Callback} to get the result callback. */ public class LocalBluetoothLeBroadcastAssistant implements BluetoothLeBroadcastAssistant.Callback { public class LocalBluetoothLeBroadcastAssistant implements LocalBluetoothProfile { private static final String TAG = "LocalBluetoothLeBroadcastAssistant"; private static final int UNKNOWN_VALUE_PLACEHOLDER = -1; private static final boolean DEBUG = BluetoothUtils.D; static final String NAME = "LE_AUDIO_BROADCAST_ASSISTANT"; // Order of this profile in device profiles list private static final int ORDINAL = 1; private LocalBluetoothProfileManager mProfileManager; private BluetoothLeBroadcastAssistant mBluetoothLeBroadcastAssistant; private BluetoothLeBroadcastAssistant mService; private final CachedBluetoothDeviceManager mDeviceManager; private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata; private BluetoothLeBroadcastMetadata.Builder mBuilder; private boolean mIsProfileReady; Loading @@ -49,30 +65,55 @@ public class LocalBluetoothLeBroadcastAssistant implements private final ServiceListener mServiceListener = new ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) { if (profile != BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) { Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST_ASSISTANT"); return; } if (DEBUG) { Log.d(TAG, "Bluetooth service connected"); } mBluetoothLeBroadcastAssistant = (BluetoothLeBroadcastAssistant) proxy; mService = (BluetoothLeBroadcastAssistant) proxy; // We just bound to the service, so refresh the UI for any connected LeAudio devices. List<BluetoothDevice> deviceList = mService.getConnectedDevices(); while (!deviceList.isEmpty()) { BluetoothDevice nextDevice = deviceList.remove(0); CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice); // we may add a new device here, but generally this should not happen if (device == null) { if (DEBUG) { Log.d(TAG, "LocalBluetoothLeBroadcastAssistant found new device: " + nextDevice); } device = mDeviceManager.addDevice(nextDevice); } device.onProfileStateChanged(LocalBluetoothLeBroadcastAssistant.this, BluetoothProfile.STATE_CONNECTED); device.refresh(); } mProfileManager.callServiceConnectedListeners(); mIsProfileReady = true; } } @Override public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) { if (profile != BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) { Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST_ASSISTANT"); return; } if (DEBUG) { Log.d(TAG, "Bluetooth service disconnected"); } mProfileManager.callServiceDisconnectedListeners(); mIsProfileReady = false; } } }; public LocalBluetoothLeBroadcastAssistant(Context context, CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { mProfileManager = profileManager; mDeviceManager = deviceManager; BluetoothAdapter.getDefaultAdapter(). getProfileProxy(context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); Loading @@ -90,7 +131,11 @@ public class LocalBluetoothLeBroadcastAssistant implements */ public void addSource(BluetoothDevice sink, BluetoothLeBroadcastMetadata metadata, boolean isGroupOp) { mBluetoothLeBroadcastAssistant.addSource(sink, metadata, isGroupOp); if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return; } mService.addSource(sink, metadata, isGroupOp); } /** Loading Loading @@ -120,13 +165,9 @@ public class LocalBluetoothLeBroadcastAssistant implements if (DEBUG) { Log.d(TAG, "addSource()"); } if (mBluetoothLeBroadcastAssistant == null) { Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return ; } buildMetadata(sourceAddressType, presentationDelayMicros, sourceAdvertisingSid, broadcastId, paSyncInterval, isEncrypted, broadcastCode, sourceDevice); mBluetoothLeBroadcastAssistant.addSource(sink, mBluetoothLeBroadcastMetadata, isGroupOp); addSource(sink, mBluetoothLeBroadcastMetadata, isGroupOp); } private void buildMetadata(int sourceAddressType, int presentationDelayMicros, Loading @@ -147,101 +188,143 @@ public class LocalBluetoothLeBroadcastAssistant implements if (DEBUG) { Log.d(TAG, "removeSource()"); } if (mBluetoothLeBroadcastAssistant == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return; } mBluetoothLeBroadcastAssistant.removeSource(sink, sourceId); mService.removeSource(sink, sourceId); } public void startSearchingForSources(@NonNull List<android.bluetooth.le.ScanFilter> filters) { if (DEBUG) { Log.d(TAG, "startSearchingForSources()"); } if (mBluetoothLeBroadcastAssistant == null) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcastAssistant is null"); return; } mBluetoothLeBroadcastAssistant.startSearchingForSources(filters); mService.startSearchingForSources(filters); } @Override public void onSourceAdded(@NonNull BluetoothDevice sink, int sourceId, int reason) { if (DEBUG) { Log.d(TAG, "onSourceAdded(), reason = " + reason + " , sourceId = " + sourceId); public void registerServiceCallBack(@NonNull @CallbackExecutor Executor executor, @NonNull BluetoothLeBroadcastAssistant.Callback callback) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return; } mService.registerCallback(executor, callback); } @Override public void onSourceAddFailed(@NonNull BluetoothDevice sink, @NonNull BluetoothLeBroadcastMetadata source, int reason) { if (DEBUG) { Log.d(TAG, "onSourceAddFailed(), reason = " + reason); public void unregisterServiceCallBack( @NonNull BluetoothLeBroadcastAssistant.Callback callback) { if (mService == null) { Log.d(TAG, "The BluetoothLeBroadcast is null."); return; } mService.unregisterCallback(callback); } @Override public void onSourceRemoved(@NonNull BluetoothDevice sink, int sourceId, int reason) { if (DEBUG) { Log.d(TAG, "onSourceRemoved(), reason = " + reason + " , sourceId = " + sourceId); public boolean isProfileReady() { return mIsProfileReady; } public int getProfileId() { return BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT; } @Override public void onSourceRemoveFailed(@NonNull BluetoothDevice sink, int sourceId, int reason) { if (DEBUG) { Log.d(TAG, "onSourceRemoveFailed(), reason = " + reason + " , sourceId = " + sourceId); public boolean accessProfileEnabled() { return false; } public boolean isAutoConnectable() { return true; } @Override public void onSearchStarted(int reason) { if (DEBUG) { Log.d(TAG, "onSearchStarted(), reason = " + reason); public int getConnectionStatus(BluetoothDevice device) { if (mService == null) { return BluetoothProfile.STATE_DISCONNECTED; } // LE Audio Broadcasts are not connection-oriented. return mService.getConnectionState(device); } @Override public void onSearchStartFailed(int reason) { if (DEBUG) { Log.d(TAG, "onSearchStartFailed(), reason = " + reason); public List<BluetoothDevice> getConnectedDevices() { if (mService == null) { return new ArrayList<BluetoothDevice>(0); } return mService.getDevicesMatchingConnectionStates( new int[]{BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTING}); } @Override public void onSearchStopped(int reason) { if (DEBUG) { Log.d(TAG, "onSearchStopped(), reason = " + reason); public boolean isEnabled(BluetoothDevice device) { if (mService == null || device == null) { return false; } return mService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN; } @Override public void onSearchStopFailed(int reason) { if (DEBUG) { Log.d(TAG, "onSearchStopFailed(), reason = " + reason); public int getConnectionPolicy(BluetoothDevice device) { if (mService == null || device == null) { return CONNECTION_POLICY_FORBIDDEN; } return mService.getConnectionPolicy(device); } @Override public void onSourceFound(@NonNull BluetoothLeBroadcastMetadata source) { public boolean setEnabled(BluetoothDevice device, boolean enabled) { boolean isEnabled = false; if (mService == null || device == null) { return false; } if (enabled) { if (mService.getConnectionPolicy(device) < CONNECTION_POLICY_ALLOWED) { isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED); } } else { isEnabled = mService.setConnectionPolicy(device, CONNECTION_POLICY_FORBIDDEN); } @Override public void onSourceModified(@NonNull BluetoothDevice sink, int sourceId, int reason) { return isEnabled; } @Override public void onSourceModifyFailed(@NonNull BluetoothDevice sink, int sourceId, int reason) { public String toString() { return NAME; } @Override public void onReceiveStateChanged(@NonNull BluetoothDevice sink, int sourceId, @NonNull BluetoothLeBroadcastReceiveState state) { public int getOrdinal() { return ORDINAL; } public boolean isProfileReady() { return mIsProfileReady; public int getNameResource(BluetoothDevice device) { return R.string.summary_empty; } public int getSummaryResourceForDevice(BluetoothDevice device) { int state = getConnectionStatus(device); return BluetoothUtils.getConnectionStateSummary(state); } public int getDrawableResource(BluetoothClass btClass) { return 0; } @RequiresApi(Build.VERSION_CODES.S) protected void finalize() { if (DEBUG) { Log.d(TAG, "finalize()"); } if (mService != null) { try { BluetoothAdapter.getDefaultAdapter().closeProfileProxy( BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, mService); mService = null; } catch (Throwable t) { Log.w(TAG, "Error cleaning up LeAudio proxy", t); } } } }
packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +30 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes