diff options
Diffstat (limited to 'le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/StreamAudioService.java')
-rw-r--r-- | le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/StreamAudioService.java | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/StreamAudioService.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/StreamAudioService.java new file mode 100644 index 000000000..fc4270377 --- /dev/null +++ b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/StreamAudioService.java @@ -0,0 +1,382 @@ +/****************************************************************************** + * + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + + +package com.android.bluetooth.apm; + +import static com.android.bluetooth.Utils.enforceBluetoothPermission; +import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; + +import android.bluetooth.BluetoothCodecConfig; +import android.bluetooth.BluetoothCodecStatus; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.IBluetoothVcp; + +import android.os.Binder; +import android.os.HandlerThread; +import android.os.Handler; +import android.os.Message; +import android.os.SystemProperties; +import android.util.Log; + +import com.android.bluetooth.btservice.AdapterService; +import com.android.bluetooth.btservice.ProfileService; +import com.android.bluetooth.acm.AcmService; + +public class StreamAudioService extends ProfileService { + private static final boolean DBG = true; + private static final String TAG = "APM: StreamAudioService:"; + public static final int LE_AUDIO_UNICAST = 26; + + public static final String CoordinatedAudioServiceName = "com.android.bluetooth.acm.AcmService"; + public static final int COORDINATED_AUDIO_UNICAST = AcmService.ACM_AUDIO_UNICAST; + + private static StreamAudioService sStreamAudioService; + private ActiveDeviceManagerService mActiveDeviceManager; + private MediaAudio mMediaAudio; + private VolumeManager mVolumeManager; + private final Object mVolumeManagerLock = new Object(); + @Override + protected void create() { + Log.i(TAG, "create()"); + } + + private static final int BAP = 0x01; + private static final int GCP = 0x02; + private static final int WMCP = 0x04; + private static final int VMCP = 0x08; + private static final int BAP_CALL = 0x10; + + private static final int MEDIA_CONTEXT = 1; + private static final int VOICE_CONTEXT = 2; + + @Override + protected boolean start() { + if(sStreamAudioService != null) { + Log.i(TAG, "StreamAudioService already started"); + return true; + } + Log.i(TAG, "start()"); + + ApmConst.setLeAudioEnabled(true); + ApmConstIntf.init(); + + setStreamAudioService(this); + + mActiveDeviceManager = ActiveDeviceManagerService.get(this); + mMediaAudio = MediaAudio.init(this); + + DeviceProfileMap dpm = DeviceProfileMap.getDeviceProfileMapInstance(); + dpm.init(this); + CallAudio mCallAudio = CallAudio.init(this); + synchronized (mVolumeManagerLock) { + mVolumeManager = VolumeManager.init(this); + } + + Log.i(TAG, "start() complete"); + return true; + } + + @Override + protected boolean stop() { + Log.w(TAG, "stop() called"); + if (sStreamAudioService == null) { + Log.w(TAG, "stop() called before start()"); + return true; + } + + if (mActiveDeviceManager != null) { + mActiveDeviceManager.disable(); + mActiveDeviceManager.cleanup(); + } + + DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); + dMap.cleanup(); + return true; + } + + @Override + protected void cleanup() { + Log.i(TAG, "cleanup()"); + synchronized (mVolumeManagerLock) { + mVolumeManager.cleanup(); + mVolumeManager = null; + } + setStreamAudioService(null); + } + + public boolean connectLeStream(BluetoothDevice device, int profile) { + AcmService mAcmService = AcmService.getAcmService(); + int mContext = getContext(profile); + + if(mContext == 0) { + Log.e(TAG, "No valid context for profiles passed"); + return false; + } + return mAcmService.connect(device, mContext, getAcmProfileID(profile), MEDIA_CONTEXT); + //return mAcmService.connect(device, VOICE_CONTEXT, BAP_CALL, VOICE_CONTEXT); + //return mAcmService.connect(device, MEDIA_CONTEXT, BAP|WMCP, MEDIA_CONTEXT); + } + + public boolean disconnectLeStream(BluetoothDevice device, boolean callAudio, boolean mediaAudio) { + AcmService mAcmService = AcmService.getAcmService(); + if(callAudio && mediaAudio) + return mAcmService.disconnect(device, VOICE_CONTEXT | MEDIA_CONTEXT); + //return mAcmService.disconnect(device, VOICE_CONTEXT); + //return mAcmService.disconnect(device, MEDIA_CONTEXT); + else if(mediaAudio) + return mAcmService.disconnect(device, MEDIA_CONTEXT); + else if(callAudio) + return mAcmService.disconnect(device, VOICE_CONTEXT); + + return false; + } + + public boolean startStream(BluetoothDevice device) { + AcmService mAcmService = AcmService.getAcmService(); + return mAcmService.StartStream(device, VOICE_CONTEXT); + } + + public boolean stopStream(BluetoothDevice device) { + AcmService mAcmService = AcmService.getAcmService(); + return mAcmService.StopStream(device, VOICE_CONTEXT); + } + + public int setActiveDevice(BluetoothDevice device, int profile, boolean playReq) { + AcmService mAcmService = AcmService.getAcmService(); + if (mAcmService == null && device == null) { + Log.w(TAG, ": device is null, fake success."); + return mActiveDeviceManager.SHO_SUCCESS; + } + + if(ApmConst.AudioProfiles.BAP_MEDIA == profile) { + return mAcmService.setActiveDevice(device, MEDIA_CONTEXT, BAP, playReq); + } else if(ApmConst.AudioProfiles.BAP_GCP == profile){ + return mAcmService.setActiveDevice(device, MEDIA_CONTEXT, GCP, playReq); + } else if(ApmConst.AudioProfiles.BAP_RECORDING == profile){ + return mAcmService.setActiveDevice(device, MEDIA_CONTEXT, WMCP, playReq); + } else { + return mAcmService.setActiveDevice(device, VOICE_CONTEXT, BAP_CALL, playReq); + //return mAcmService.setActiveDevice(device, MEDIA_CONTEXT, BAP, playReq); + } + } + + public void setCodecConfig(BluetoothDevice device, String codecID, int channelMode) { + AcmService mAcmService = AcmService.getAcmService(); + mAcmService.ChangeCodecConfigPreference(device, codecID); + } + + public BluetoothDevice getDeviceGroup(BluetoothDevice device){ + AcmService mAcmService = AcmService.getAcmService(); + return mAcmService.getGroup(device); + } + + public void onConnectionStateChange(BluetoothDevice device, int state, int audioType, boolean primeDevice) { + MediaAudio mMediaAudio = MediaAudio.get(); + CallAudio mCallAudio = CallAudio.get(); + int profile = ApmConst.AudioFeatures.MAX_AUDIO_FEATURES; + if(audioType == ApmConst.AudioFeatures.CALL_AUDIO) { + mCallAudio.onConnStateChange(device, state, ApmConst.AudioProfiles.BAP_CALL); + } else if(audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) { + boolean isCsipDevice = (device != null) && + getDeviceGroup(device).getAddress().contains(ApmConst.groupAddress); + if(isCsipDevice) + mMediaAudio.onConnStateChange(device, state, ApmConst.AudioProfiles.BAP_MEDIA, primeDevice); + else + mMediaAudio.onConnStateChange(device, state, ApmConst.AudioProfiles.BAP_MEDIA); + } + } + + public void onStreamStateChange(BluetoothDevice device, int state, int audioType) { + MediaAudio mMediaAudio = MediaAudio.get(); + CallAudio mCallAudio = CallAudio.get(); + if(audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) + mMediaAudio.onStreamStateChange(device, state); + else if(audioType == ApmConst.AudioFeatures.CALL_AUDIO) + mCallAudio.onAudioStateChange(device, state); + } + + public void onActiveDeviceChange(BluetoothDevice device, int audioType) { + if (mActiveDeviceManager != null) + mActiveDeviceManager.onActiveDeviceChange(device, audioType); + } + + public void onMediaCodecConfigChange(BluetoothDevice device, BluetoothCodecStatus codecStatus, int audioType) { + MediaAudio mMediaAudio = MediaAudio.get(); + mMediaAudio.onCodecConfigChange(device, codecStatus, ApmConst.AudioProfiles.BAP_MEDIA); + } + + public void onMediaCodecConfigChange(BluetoothDevice device, BluetoothCodecStatus codecStatus, int audioType, boolean updateAudio) { + MediaAudio mMediaAudio = MediaAudio.get(); + mMediaAudio.onCodecConfigChange(device, codecStatus, ApmConst.AudioProfiles.BAP_MEDIA, updateAudio); + } + + public void setCallAudioParam(String param) { + CallAudio mCallAudio = CallAudio.get(); + mCallAudio.setAudioParam(param); + } + + public void setCallAudioOn(boolean on) { + CallAudio mCallAudio = CallAudio.get(); + mCallAudio.setBluetoothScoOn(on); + } + + public int getVcpConnState(BluetoothDevice device) { + synchronized (mVolumeManagerLock) { + if (mVolumeManager == null) + return BluetoothProfile.STATE_DISCONNECTED; + return mVolumeManager.getConnectionState(device); + } + } + + public int getConnectionMode(BluetoothDevice device) { + synchronized (mVolumeManagerLock) { + if (mVolumeManager == null) + return BluetoothProfile.STATE_DISCONNECTED; + return mVolumeManager.getConnectionMode(device); + } + } + + public void setAbsoluteVolume(BluetoothDevice device, int volume) { + synchronized (mVolumeManagerLock) { + if (mVolumeManager != null) + mVolumeManager.updateBroadcastVolume(device, volume); + } + } + + public int getAbsoluteVolume(BluetoothDevice device) { + synchronized (mVolumeManagerLock) { + if (mVolumeManager == null) + return 7; + return mVolumeManager.getBassVolume(device); + } + } + + public void setMute(BluetoothDevice device, boolean muteStatus) { + synchronized (mVolumeManagerLock) { + if (mVolumeManager != null) + mVolumeManager.setMute(device, muteStatus); + } + } + + public boolean isMute(BluetoothDevice device) { + synchronized (mVolumeManagerLock) { + if (mVolumeManager == null) + return false; + return mVolumeManager.getMuteStatus(device); + } + } + + private int getContext(int profileID) { + int context = 0; + if((DeviceProfileMap.getLeMediaProfiles() & profileID) > 0) { + context = (context|MEDIA_CONTEXT); + } + + if((DeviceProfileMap.getLeCallProfiles() & profileID) > 0) { + context = (context|VOICE_CONTEXT); + } + return context; + } + + private int getAcmProfileID (int ProfileID) { + int AcmProfileID = 0; + if((ApmConst.AudioProfiles.BAP_MEDIA & ProfileID) == ApmConst.AudioProfiles.BAP_MEDIA) + AcmProfileID = BAP; + if((ApmConst.AudioProfiles.BAP_CALL & ProfileID) == ApmConst.AudioProfiles.BAP_CALL) + AcmProfileID = AcmProfileID | BAP_CALL; + if((ApmConst.AudioProfiles.BAP_GCP & ProfileID) == ApmConst.AudioProfiles.BAP_GCP) + AcmProfileID = AcmProfileID | GCP; + if((ApmConst.AudioProfiles.BAP_RECORDING & ProfileID) == ApmConst.AudioProfiles.BAP_RECORDING) + AcmProfileID = AcmProfileID | WMCP; + return AcmProfileID; + } + + @Override + protected IProfileServiceBinder initBinder() { + return new LeAudioUnicastBinder(this); + } + + private static class LeAudioUnicastBinder extends IBluetoothVcp.Stub implements IProfileServiceBinder { + + StreamAudioService mService; + LeAudioUnicastBinder(StreamAudioService service) { + mService = service; + } + + @Override + public void cleanup() { + } + + @Override + public int getConnectionState(BluetoothDevice device) { + if(mService == null) + return BluetoothProfile.STATE_DISCONNECTED; + return mService.getVcpConnState(device); + } + + @Override + public int getConnectionMode(BluetoothDevice device) { + if(mService != null) { + return mService.getConnectionMode(device); + } + return 0; + } + + @Override + public void setAbsoluteVolume(BluetoothDevice device, int volume) { + if(mService != null) { + mService.setAbsoluteVolume(device, volume); + } + } + + @Override + public int getAbsoluteVolume(BluetoothDevice device) { + if(mService == null) + return 7; + return mService.getAbsoluteVolume(device); + } + + @Override + public void setMute (BluetoothDevice device, boolean enableMute) { + if(mService != null) { + mService.setMute(device, enableMute); + } + } + + @Override + public boolean isMute(BluetoothDevice device) { + if(mService != null) { + return mService.isMute(device); + } + return false; + } + } + + public static StreamAudioService getStreamAudioService() { + return sStreamAudioService; + } + + private static synchronized void setStreamAudioService(StreamAudioService instance) { + if (DBG) { + Log.d(TAG, "setStreamAudioService(): set to: " + instance); + } + sStreamAudioService = instance; + } +} |