• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.vc;
18 
19 import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED;
20 import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE;
21 import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED;
22 import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED;
23 import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED;
24 import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED;
25 
26 import static java.util.Objects.requireNonNull;
27 
28 import android.bluetooth.AudioInputControl.AudioInputStatus;
29 import android.bluetooth.AudioInputControl.AudioInputType;
30 import android.bluetooth.AudioInputControl.GainMode;
31 import android.bluetooth.AudioInputControl.Mute;
32 import android.bluetooth.BluetoothDevice;
33 import android.util.Log;
34 
35 import com.android.bluetooth.btservice.AdapterService;
36 import com.android.internal.annotations.VisibleForTesting;
37 
38 import java.util.Arrays;
39 import java.util.function.Consumer;
40 
41 class VolumeControlNativeCallback {
42     private static final String TAG = VolumeControlNativeCallback.class.getSimpleName();
43 
44     private final AdapterService mAdapterService;
45     private final VolumeControlService mVolumeControlService;
46 
VolumeControlNativeCallback( AdapterService adapterService, VolumeControlService volumeControlService)47     VolumeControlNativeCallback(
48             AdapterService adapterService, VolumeControlService volumeControlService) {
49         mAdapterService = requireNonNull(adapterService);
50         mVolumeControlService = requireNonNull(volumeControlService);
51     }
52 
getDevice(byte[] address)53     private BluetoothDevice getDevice(byte[] address) {
54         return mAdapterService.getDeviceFromByte(address);
55     }
56 
sendMessageToService(Consumer<VolumeControlService> action)57     private void sendMessageToService(Consumer<VolumeControlService> action) {
58         if (!mVolumeControlService.isAvailable()) {
59             StringBuilder sb = new StringBuilder();
60             Arrays.stream(new Throwable().getStackTrace())
61                     .skip(1) // skip the inlineStackTrace method in the outputted stack trace
62                     .forEach(trace -> sb.append(" [at ").append(trace).append("]"));
63             Log.e(TAG, "Action ignored, service not available: " + sb.toString());
64             return;
65         }
66         action.accept(mVolumeControlService);
67     }
68 
69     @VisibleForTesting
onConnectionStateChanged(int state, byte[] address)70     void onConnectionStateChanged(int state, byte[] address) {
71         VolumeControlStackEvent event =
72                 new VolumeControlStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED);
73         event.device = getDevice(address);
74         event.valueInt1 = state;
75 
76         Log.d(TAG, "onConnectionStateChanged: " + event);
77         mVolumeControlService.messageFromNative(event);
78     }
79 
80     @VisibleForTesting
onVolumeStateChanged( int volume, boolean mute, int flags, byte[] address, boolean isAutonomous)81     void onVolumeStateChanged(
82             int volume, boolean mute, int flags, byte[] address, boolean isAutonomous) {
83         VolumeControlStackEvent event =
84                 new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED);
85         event.device = getDevice(address);
86         event.valueInt1 = -1;
87         event.valueInt2 = volume;
88         event.valueInt3 = flags;
89         event.valueBool1 = mute;
90         event.valueBool2 = isAutonomous;
91 
92         Log.d(TAG, "onVolumeStateChanged: " + event);
93         mVolumeControlService.messageFromNative(event);
94     }
95 
96     @VisibleForTesting
onGroupVolumeStateChanged(int volume, boolean mute, int groupId, boolean isAutonomous)97     void onGroupVolumeStateChanged(int volume, boolean mute, int groupId, boolean isAutonomous) {
98         VolumeControlStackEvent event =
99                 new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED);
100         event.device = null;
101         event.valueInt1 = groupId;
102         event.valueInt2 = volume;
103         event.valueBool1 = mute;
104         event.valueBool2 = isAutonomous;
105 
106         Log.d(TAG, "onGroupVolumeStateChanged: " + event);
107         mVolumeControlService.messageFromNative(event);
108     }
109 
110     @VisibleForTesting
onDeviceAvailable(int numOfExternalOutputs, int numOfExternalInputs, byte[] address)111     void onDeviceAvailable(int numOfExternalOutputs, int numOfExternalInputs, byte[] address) {
112         VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_DEVICE_AVAILABLE);
113         event.device = getDevice(address);
114         event.valueInt1 = numOfExternalOutputs;
115         event.valueInt2 = numOfExternalInputs;
116 
117         Log.d(TAG, "onDeviceAvailable: " + event);
118         mVolumeControlService.messageFromNative(event);
119     }
120 
121     @VisibleForTesting
onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset, byte[] address)122     void onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset, byte[] address) {
123         VolumeControlStackEvent event =
124                 new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED);
125         event.device = getDevice(address);
126         event.valueInt1 = externalOutputId;
127         event.valueInt2 = offset;
128 
129         Log.d(TAG, "onExtAudioOutVolumeOffsetChanged: " + event);
130         mVolumeControlService.messageFromNative(event);
131     }
132 
133     @VisibleForTesting
onExtAudioOutLocationChanged(int externalOutputId, int location, byte[] address)134     void onExtAudioOutLocationChanged(int externalOutputId, int location, byte[] address) {
135         VolumeControlStackEvent event =
136                 new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED);
137         event.device = getDevice(address);
138         event.valueInt1 = externalOutputId;
139         event.valueInt2 = location;
140 
141         Log.d(TAG, "onExtAudioOutLocationChanged: " + event);
142         mVolumeControlService.messageFromNative(event);
143     }
144 
145     @VisibleForTesting
onExtAudioOutDescriptionChanged(int externalOutputId, String descr, byte[] address)146     void onExtAudioOutDescriptionChanged(int externalOutputId, String descr, byte[] address) {
147         VolumeControlStackEvent event =
148                 new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED);
149         event.device = getDevice(address);
150         event.valueInt1 = externalOutputId;
151         event.valueString1 = descr;
152 
153         Log.d(TAG, "onExtAudioOutLocationChanged: " + event);
154         mVolumeControlService.messageFromNative(event);
155     }
156 
157     @VisibleForTesting
onExtAudioInStateChanged( int id, int gainSetting, @Mute int mute, @GainMode int gainMode, byte[] address)158     void onExtAudioInStateChanged(
159             int id, int gainSetting, @Mute int mute, @GainMode int gainMode, byte[] address) {
160         sendMessageToService(
161                 s ->
162                         s.onExtAudioInStateChanged(
163                                 getDevice(address), id, gainSetting, mute, gainMode));
164     }
165 
166     @VisibleForTesting
onExtAudioInSetGainSettingFailed(int id, byte[] address)167     void onExtAudioInSetGainSettingFailed(int id, byte[] address) {
168         sendMessageToService(s -> s.onExtAudioInSetGainSettingFailed(getDevice(address), id));
169     }
170 
171     @VisibleForTesting
onExtAudioInSetMuteFailed(int id, byte[] address)172     void onExtAudioInSetMuteFailed(int id, byte[] address) {
173         sendMessageToService(s -> s.onExtAudioInSetMuteFailed(getDevice(address), id));
174     }
175 
176     @VisibleForTesting
onExtAudioInSetGainModeFailed(int id, byte[] address)177     void onExtAudioInSetGainModeFailed(int id, byte[] address) {
178         sendMessageToService(s -> s.onExtAudioInSetGainModeFailed(getDevice(address), id));
179     }
180 
181     @VisibleForTesting
onExtAudioInStatusChanged(int id, @AudioInputStatus int status, byte[] address)182     void onExtAudioInStatusChanged(int id, @AudioInputStatus int status, byte[] address) {
183         sendMessageToService(s -> s.onExtAudioInStatusChanged(getDevice(address), id, status));
184     }
185 
186     @VisibleForTesting
onExtAudioInTypeChanged(int id, @AudioInputType int type, byte[] address)187     void onExtAudioInTypeChanged(int id, @AudioInputType int type, byte[] address) {
188         sendMessageToService(s -> s.onExtAudioInTypeChanged(getDevice(address), id, type));
189     }
190 
191     @VisibleForTesting
onExtAudioInDescriptionChanged( int id, String description, boolean isWritable, byte[] address)192     void onExtAudioInDescriptionChanged(
193             int id, String description, boolean isWritable, byte[] address) {
194         sendMessageToService(
195                 s ->
196                         s.onExtAudioInDescriptionChanged(
197                                 getDevice(address), id, description, isWritable));
198     }
199 
200     @VisibleForTesting
onExtAudioInGainSettingPropertiesChanged( int id, int unit, int min, int max, byte[] address)201     void onExtAudioInGainSettingPropertiesChanged(
202             int id, int unit, int min, int max, byte[] address) {
203         sendMessageToService(
204                 s ->
205                         s.onExtAudioInGainSettingPropertiesChanged(
206                                 getDevice(address), id, unit, min, max));
207     }
208 }
209