blob: ff504f4716cdf145d490f37b5ef9354765a622ae [file] [log] [blame]
Hayden Gomes38e18132020-04-09 11:29:25 -07001/*
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
17package com.android.car.audio.hal;
18
19import android.hardware.automotive.audiocontrol.V2_0.IAudioControl;
20import android.hardware.automotive.audiocontrol.V2_0.ICloseHandle;
21import android.hardware.automotive.audiocontrol.V2_0.IFocusListener;
22import android.media.AudioAttributes;
23import android.media.AudioAttributes.AttributeUsage;
24import android.os.RemoteException;
25import android.util.Log;
26
27import androidx.annotation.Nullable;
28
29import java.io.PrintWriter;
30import java.util.NoSuchElementException;
31import java.util.Objects;
32
Oscar Azucenacf517e82020-05-21 16:45:43 -070033/**
34 * Wrapper for IAudioControl@2.0.
35 */
36public final class AudioControlWrapperV2 implements AudioControlWrapper {
Hayden Gomes38e18132020-04-09 11:29:25 -070037 private static final String TAG = AudioControlWrapperV2.class.getSimpleName();
38
39 private IAudioControl mAudioControlV2;
40
Hayden Gomes890ad022020-04-09 15:53:58 -070041 private AudioControlDeathRecipient mDeathRecipient;
Hayden Gomes38e18132020-04-09 11:29:25 -070042 private ICloseHandle mCloseHandle;
43
44 public static @Nullable IAudioControl getService() {
45 try {
46 return IAudioControl.getService(true);
47 } catch (RemoteException e) {
48 throw new IllegalStateException("Failed to get IAudioControl@2.0 service", e);
49 } catch (NoSuchElementException e) {
50 return null;
51 }
52 }
53
54 AudioControlWrapperV2(IAudioControl audioControlV2) {
55 mAudioControlV2 = Objects.requireNonNull(audioControlV2);
56 }
57
58 @Override
59 public void unregisterFocusListener() {
60 if (mCloseHandle != null) {
61 try {
62 mCloseHandle.close();
63 } catch (RemoteException e) {
64 Log.e(TAG, "Failed to close focus listener", e);
65 } finally {
66 mCloseHandle = null;
67 }
68 }
69 }
70
71 @Override
72 public boolean supportsHalAudioFocus() {
73 return true;
74 }
75
76 @Override
77 public void registerFocusListener(IFocusListener focusListener) {
78 Log.d(TAG, "Registering focus listener on AudioControl HAL");
79 try {
80 mCloseHandle = mAudioControlV2.registerFocusListener(focusListener);
81 } catch (RemoteException e) {
82 Log.e(TAG, "Failed to register focus listener");
83 throw new IllegalStateException("IAudioControl#registerFocusListener failed", e);
84 }
85 }
86
87 @Override
88 public void onAudioFocusChange(@AttributeUsage int usage, int zoneId, int focusChange) {
89 if (Log.isLoggable(TAG, Log.DEBUG)) {
90 Log.d(TAG, "onAudioFocusChange: usage " + AudioAttributes.usageToString(usage)
91 + ", zoneId " + zoneId + ", focusChange " + focusChange);
92 }
93 try {
94 mAudioControlV2.onAudioFocusChange(usage, zoneId, focusChange);
95 } catch (RemoteException e) {
96 throw new IllegalStateException("Failed to query IAudioControl#onAudioFocusChange", e);
97 }
98 }
99
100 /**
101 * Dumps the current state of the {@code AudioControlWrapperV2}.
102 *
103 * @param indent indent to append to each new line.
104 * @param writer stream to write current state.
105 */
106 @Override
107 public void dump(String indent, PrintWriter writer) {
108 writer.printf("%s*AudioControlWrapperV2*\n", indent);
109 writer.printf("%s\tFocus listener registered on HAL? %b", indent, (mCloseHandle != null));
110 }
111
112 @Override
113 public void setFadeTowardFront(float value) {
114 try {
115 mAudioControlV2.setFadeTowardFront(value);
116 } catch (RemoteException e) {
117 Log.e(TAG, "setFadeTowardFront failed", e);
118 }
119 }
120
121 @Override
122 public void setBalanceTowardRight(float value) {
123 try {
124 mAudioControlV2.setBalanceTowardRight(value);
125 } catch (RemoteException e) {
126 Log.e(TAG, "setBalanceTowardRight failed", e);
127 }
128 }
Hayden Gomes890ad022020-04-09 15:53:58 -0700129
130 @Override
131 public void linkToDeath(@Nullable AudioControlDeathRecipient deathRecipient) {
132 try {
133 mAudioControlV2.linkToDeath(this::serviceDied, 0);
134 mDeathRecipient = deathRecipient;
135 } catch (RemoteException e) {
136 throw new IllegalStateException("Call to IAudioControl@2.0#linkToDeath failed", e);
137 }
138 }
139
140 @Override
141 public void unlinkToDeath() {
142 try {
143 mAudioControlV2.unlinkToDeath(this::serviceDied);
144 mDeathRecipient = null;
145 } catch (RemoteException e) {
146 throw new IllegalStateException("Call to IAudioControl@2.0#unlinkToDeath failed", e);
147 }
148 }
149
150 private void serviceDied(long cookie) {
151 Log.w(TAG, "IAudioControl@2.0 died. Fetching new handle");
152 mAudioControlV2 = AudioControlWrapperV2.getService();
153 linkToDeath(mDeathRecipient);
154 if (mDeathRecipient != null) {
155 mDeathRecipient.serviceDied();
156 }
157 }
Hayden Gomes38e18132020-04-09 11:29:25 -0700158}