• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.car.audio.hal;
18 
19 import static android.car.builtin.media.AudioManagerHelper.usageToString;
20 
21 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.car.builtin.util.Slogf;
26 import android.hardware.automotive.audiocontrol.MutingInfo;
27 import android.hardware.automotive.audiocontrol.V2_0.IAudioControl;
28 import android.hardware.automotive.audiocontrol.V2_0.ICloseHandle;
29 import android.hardware.automotive.audiocontrol.V2_0.IFocusListener;
30 import android.os.RemoteException;
31 import android.util.Log;
32 
33 import com.android.car.CarLog;
34 import com.android.car.audio.CarDuckingInfo;
35 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
36 import com.android.car.internal.annotation.AttributeUsage;
37 import com.android.car.internal.util.IndentingPrintWriter;
38 
39 import java.util.List;
40 import java.util.NoSuchElementException;
41 import java.util.Objects;
42 
43 /**
44  * Wrapper for IAudioControl@2.0.
45  */
46 public final class AudioControlWrapperV2 implements AudioControlWrapper {
47     private static final String TAG = CarLog.tagFor(AudioControlWrapperV2.class);
48 
49     private IAudioControl mAudioControlV2;
50 
51     private AudioControlDeathRecipient mDeathRecipient;
52     private ICloseHandle mCloseHandle;
53 
getService()54     static @Nullable IAudioControl getService() {
55         try {
56             return IAudioControl.getService(true);
57         } catch (RemoteException e) {
58             throw new IllegalStateException("Failed to get IAudioControl@2.0 service", e);
59         } catch (NoSuchElementException e) {
60             return null;
61         }
62     }
63 
AudioControlWrapperV2(IAudioControl audioControlV2)64     AudioControlWrapperV2(IAudioControl audioControlV2) {
65         mAudioControlV2 = Objects.requireNonNull(audioControlV2);
66     }
67 
68     @Override
unregisterFocusListener()69     public void unregisterFocusListener() {
70         if (mCloseHandle != null) {
71             try {
72                 mCloseHandle.close();
73             } catch (RemoteException e) {
74                 Slogf.e(TAG, "Failed to close focus listener", e);
75             } finally {
76                 mCloseHandle = null;
77             }
78         }
79     }
80 
81     @Override
supportsFeature(int feature)82     public boolean supportsFeature(int feature) {
83         if (feature == AUDIOCONTROL_FEATURE_AUDIO_FOCUS) {
84             return true;
85         }
86         return false;
87     }
88 
89     @Override
registerFocusListener(HalFocusListener focusListener)90     public void registerFocusListener(HalFocusListener focusListener) {
91         Slogf.d(TAG, "Registering focus listener on AudioControl HAL");
92         IFocusListener listenerWrapper = new FocusListenerWrapper(focusListener);
93         try {
94             mCloseHandle = mAudioControlV2.registerFocusListener(listenerWrapper);
95         } catch (RemoteException e) {
96             Slogf.e(TAG, "Failed to register focus listener");
97             throw new IllegalStateException("IAudioControl#registerFocusListener failed", e);
98         }
99     }
100 
101     @Override
registerAudioGainCallback(HalAudioGainCallback gainCallback)102     public void registerAudioGainCallback(HalAudioGainCallback gainCallback) {
103         throw new UnsupportedOperationException(
104                 "Audio Gain Callback is unsupported for IAudioControl@2.0");
105     }
106 
107     @Override
unregisterAudioGainCallback()108     public void unregisterAudioGainCallback() {
109         throw new UnsupportedOperationException(
110                 "Audio Gain Callback is unsupported for IAudioControl@2.0");
111     }
112 
113     @Override
onAudioFocusChange(@ttributeUsage int usage, int zoneId, int focusChange)114     public void onAudioFocusChange(@AttributeUsage int usage, int zoneId, int focusChange) {
115         if (Slogf.isLoggable(TAG, Log.DEBUG)) {
116             Slogf.d(TAG, "onAudioFocusChange: usage " + usageToString(usage)
117                     + ", zoneId " + zoneId + ", focusChange " + focusChange);
118         }
119         try {
120             mAudioControlV2.onAudioFocusChange(usage, zoneId, focusChange);
121         } catch (RemoteException e) {
122             throw new IllegalStateException("Failed to query IAudioControl#onAudioFocusChange", e);
123         }
124     }
125 
126     @Override
127     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dump(IndentingPrintWriter writer)128     public void dump(IndentingPrintWriter writer) {
129         writer.println("*AudioControlWrapperV2*");
130         writer.increaseIndent();
131         writer.printf("Focus listener registered on HAL? %b\n", (mCloseHandle != null));
132 
133         writer.println("Supported Features");
134         writer.increaseIndent();
135         writer.println("- AUDIOCONTROL_FEATURE_AUDIO_FOCUS");
136         writer.decreaseIndent();
137 
138         writer.decreaseIndent();
139     }
140 
141     @Override
setFadeTowardFront(float value)142     public void setFadeTowardFront(float value) {
143         try {
144             mAudioControlV2.setFadeTowardFront(value);
145         } catch (RemoteException e) {
146             Slogf.e(TAG, "setFadeTowardFront failed", e);
147         }
148     }
149 
150     @Override
setBalanceTowardRight(float value)151     public void setBalanceTowardRight(float value) {
152         try {
153             mAudioControlV2.setBalanceTowardRight(value);
154         } catch (RemoteException e) {
155             Slogf.e(TAG, "setBalanceTowardRight failed", e);
156         }
157     }
158 
159     @Override
onDevicesToDuckChange(List<CarDuckingInfo> carDuckingInfos)160     public void onDevicesToDuckChange(List<CarDuckingInfo> carDuckingInfos) {
161         throw new UnsupportedOperationException("HAL ducking is unsupported for IAudioControl@2.0");
162     }
163 
164     @Override
onDevicesToMuteChange(@onNull List<MutingInfo> carZonesMutingInfo)165     public void onDevicesToMuteChange(@NonNull List<MutingInfo> carZonesMutingInfo) {
166         throw new UnsupportedOperationException("HAL muting is unsupported for IAudioControl@2.0");
167     }
168 
169     @Override
linkToDeath(@ullable AudioControlDeathRecipient deathRecipient)170     public void linkToDeath(@Nullable AudioControlDeathRecipient deathRecipient) {
171         try {
172             mAudioControlV2.linkToDeath(this::serviceDied, 0);
173             mDeathRecipient = deathRecipient;
174         } catch (RemoteException e) {
175             throw new IllegalStateException("Call to IAudioControl@2.0#linkToDeath failed", e);
176         }
177     }
178 
179     @Override
unlinkToDeath()180     public void unlinkToDeath() {
181         try {
182             mAudioControlV2.unlinkToDeath(this::serviceDied);
183             mDeathRecipient = null;
184         } catch (RemoteException e) {
185             throw new IllegalStateException("Call to IAudioControl@2.0#unlinkToDeath failed", e);
186         }
187     }
188 
serviceDied(long cookie)189     private void serviceDied(long cookie) {
190         Slogf.w(TAG, "IAudioControl@2.0 died. Fetching new handle");
191         mAudioControlV2 = AudioControlWrapperV2.getService();
192         linkToDeath(mDeathRecipient);
193         if (mDeathRecipient != null) {
194             mDeathRecipient.serviceDied();
195         }
196     }
197 
198     private final class FocusListenerWrapper extends IFocusListener.Stub {
199         private final HalFocusListener mListener;
200 
FocusListenerWrapper(HalFocusListener halFocusListener)201         FocusListenerWrapper(HalFocusListener halFocusListener) {
202             mListener = halFocusListener;
203         }
204 
205         @Override
requestAudioFocus(int usage, int zoneId, int focusGain)206         public void requestAudioFocus(int usage, int zoneId, int focusGain) throws RemoteException {
207             mListener.requestAudioFocus(usage, zoneId, focusGain);
208         }
209 
210         @Override
abandonAudioFocus(int usage, int zoneId)211         public void abandonAudioFocus(int usage, int zoneId) throws RemoteException {
212             mListener.abandonAudioFocus(usage, zoneId);
213         }
214     }
215 }
216