• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright 2007, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #define LOG_TAG "IAudioTrack"
19 //#define LOG_NDEBUG 0
20 #include <utils/Log.h>
21 
22 #include <stdint.h>
23 #include <sys/types.h>
24 
25 #include <binder/Parcel.h>
26 
27 #include <media/IAudioTrack.h>
28 
29 namespace android {
30 
31 using media::VolumeShaper;
32 
33 enum {
34     GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
35     START,
36     STOP,
37     FLUSH,
38     RESERVED, // was MUTE
39     PAUSE,
40     ATTACH_AUX_EFFECT,
41     SET_PARAMETERS,
42     GET_TIMESTAMP,
43     SIGNAL,
44     APPLY_VOLUME_SHAPER,
45     GET_VOLUME_SHAPER_STATE,
46 };
47 
48 class BpAudioTrack : public BpInterface<IAudioTrack>
49 {
50 public:
BpAudioTrack(const sp<IBinder> & impl)51     explicit BpAudioTrack(const sp<IBinder>& impl)
52         : BpInterface<IAudioTrack>(impl)
53     {
54     }
55 
getCblk() const56     virtual sp<IMemory> getCblk() const
57     {
58         Parcel data, reply;
59         sp<IMemory> cblk;
60         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
61         status_t status = remote()->transact(GET_CBLK, data, &reply);
62         if (status == NO_ERROR) {
63             cblk = interface_cast<IMemory>(reply.readStrongBinder());
64             if (cblk != 0 && cblk->pointer() == NULL) {
65                 cblk.clear();
66             }
67         }
68         return cblk;
69     }
70 
start()71     virtual status_t start()
72     {
73         Parcel data, reply;
74         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
75         status_t status = remote()->transact(START, data, &reply);
76         if (status == NO_ERROR) {
77             status = reply.readInt32();
78         } else {
79             ALOGW("start() error: %s", strerror(-status));
80         }
81         return status;
82     }
83 
stop()84     virtual void stop()
85     {
86         Parcel data, reply;
87         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
88         remote()->transact(STOP, data, &reply);
89     }
90 
flush()91     virtual void flush()
92     {
93         Parcel data, reply;
94         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
95         remote()->transact(FLUSH, data, &reply);
96     }
97 
pause()98     virtual void pause()
99     {
100         Parcel data, reply;
101         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
102         remote()->transact(PAUSE, data, &reply);
103     }
104 
attachAuxEffect(int effectId)105     virtual status_t attachAuxEffect(int effectId)
106     {
107         Parcel data, reply;
108         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
109         data.writeInt32(effectId);
110         status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
111         if (status == NO_ERROR) {
112             status = reply.readInt32();
113         } else {
114             ALOGW("attachAuxEffect() error: %s", strerror(-status));
115         }
116         return status;
117     }
118 
setParameters(const String8 & keyValuePairs)119     virtual status_t setParameters(const String8& keyValuePairs) {
120         Parcel data, reply;
121         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
122         data.writeString8(keyValuePairs);
123         status_t status = remote()->transact(SET_PARAMETERS, data, &reply);
124         if (status == NO_ERROR) {
125             status = reply.readInt32();
126         }
127         return status;
128     }
129 
getTimestamp(AudioTimestamp & timestamp)130     virtual status_t getTimestamp(AudioTimestamp& timestamp) {
131         Parcel data, reply;
132         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
133         status_t status = remote()->transact(GET_TIMESTAMP, data, &reply);
134         if (status == NO_ERROR) {
135             status = reply.readInt32();
136             if (status == NO_ERROR) {
137                 timestamp.mPosition = reply.readInt32();
138                 timestamp.mTime.tv_sec = reply.readInt32();
139                 timestamp.mTime.tv_nsec = reply.readInt32();
140             }
141         }
142         return status;
143     }
144 
signal()145     virtual void signal() {
146         Parcel data, reply;
147         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
148         remote()->transact(SIGNAL, data, &reply);
149     }
150 
applyVolumeShaper(const sp<VolumeShaper::Configuration> & configuration,const sp<VolumeShaper::Operation> & operation)151     virtual VolumeShaper::Status applyVolumeShaper(
152             const sp<VolumeShaper::Configuration>& configuration,
153             const sp<VolumeShaper::Operation>& operation) {
154         Parcel data, reply;
155         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
156 
157         status_t status = configuration.get() == nullptr
158                 ? data.writeInt32(0)
159                 :  data.writeInt32(1)
160                     ?: configuration->writeToParcel(&data);
161         if (status != NO_ERROR) {
162             return VolumeShaper::Status(status);
163         }
164 
165         status = operation.get() == nullptr
166                 ? status = data.writeInt32(0)
167                 : data.writeInt32(1)
168                     ?: operation->writeToParcel(&data);
169         if (status != NO_ERROR) {
170             return VolumeShaper::Status(status);
171         }
172 
173         int32_t remoteVolumeShaperStatus;
174         status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply)
175                  ?: reply.readInt32(&remoteVolumeShaperStatus);
176 
177         return VolumeShaper::Status(status ?: remoteVolumeShaperStatus);
178     }
179 
getVolumeShaperState(int id)180     virtual sp<VolumeShaper::State> getVolumeShaperState(int id) {
181         Parcel data, reply;
182         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
183 
184         data.writeInt32(id);
185         status_t status = remote()->transact(GET_VOLUME_SHAPER_STATE, data, &reply);
186         if (status != NO_ERROR) {
187             return nullptr;
188         }
189         sp<VolumeShaper::State> state = new VolumeShaper::State;
190         status = state->readFromParcel(&reply);
191         if (status != NO_ERROR) {
192             return nullptr;
193         }
194         return state;
195     }
196 };
197 
198 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
199 
200 // ----------------------------------------------------------------------
201 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)202 status_t BnAudioTrack::onTransact(
203     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
204 {
205     switch (code) {
206         case GET_CBLK: {
207             CHECK_INTERFACE(IAudioTrack, data, reply);
208             reply->writeStrongBinder(IInterface::asBinder(getCblk()));
209             return NO_ERROR;
210         } break;
211         case START: {
212             CHECK_INTERFACE(IAudioTrack, data, reply);
213             reply->writeInt32(start());
214             return NO_ERROR;
215         } break;
216         case STOP: {
217             CHECK_INTERFACE(IAudioTrack, data, reply);
218             stop();
219             return NO_ERROR;
220         } break;
221         case FLUSH: {
222             CHECK_INTERFACE(IAudioTrack, data, reply);
223             flush();
224             return NO_ERROR;
225         } break;
226         case PAUSE: {
227             CHECK_INTERFACE(IAudioTrack, data, reply);
228             pause();
229             return NO_ERROR;
230         }
231         case ATTACH_AUX_EFFECT: {
232             CHECK_INTERFACE(IAudioTrack, data, reply);
233             reply->writeInt32(attachAuxEffect(data.readInt32()));
234             return NO_ERROR;
235         } break;
236         case SET_PARAMETERS: {
237             CHECK_INTERFACE(IAudioTrack, data, reply);
238             String8 keyValuePairs(data.readString8());
239             reply->writeInt32(setParameters(keyValuePairs));
240             return NO_ERROR;
241         } break;
242         case GET_TIMESTAMP: {
243             CHECK_INTERFACE(IAudioTrack, data, reply);
244             AudioTimestamp timestamp;
245             status_t status = getTimestamp(timestamp);
246             reply->writeInt32(status);
247             if (status == NO_ERROR) {
248                 reply->writeInt32(timestamp.mPosition);
249                 reply->writeInt32(timestamp.mTime.tv_sec);
250                 reply->writeInt32(timestamp.mTime.tv_nsec);
251             }
252             return NO_ERROR;
253         } break;
254         case SIGNAL: {
255             CHECK_INTERFACE(IAudioTrack, data, reply);
256             signal();
257             return NO_ERROR;
258         } break;
259         case APPLY_VOLUME_SHAPER: {
260             CHECK_INTERFACE(IAudioTrack, data, reply);
261             sp<VolumeShaper::Configuration> configuration;
262             sp<VolumeShaper::Operation> operation;
263 
264             int32_t present;
265             status_t status = data.readInt32(&present);
266             if (status == NO_ERROR && present != 0) {
267                 configuration = new VolumeShaper::Configuration();
268                 status = configuration->readFromParcel(&data);
269             }
270             status = status ?: data.readInt32(&present);
271             if (status == NO_ERROR && present != 0) {
272                 operation = new VolumeShaper::Operation();
273                 status = operation->readFromParcel(&data);
274             }
275             if (status == NO_ERROR) {
276                 status = (status_t)applyVolumeShaper(configuration, operation);
277             }
278             reply->writeInt32(status);
279             return NO_ERROR;
280         } break;
281         case GET_VOLUME_SHAPER_STATE: {
282             CHECK_INTERFACE(IAudioTrack, data, reply);
283             int id;
284             status_t status = data.readInt32(&id);
285             if (status == NO_ERROR) {
286                 sp<VolumeShaper::State> state = getVolumeShaperState(id);
287                 if (state.get() != nullptr) {
288                      status = state->writeToParcel(reply);
289                 }
290             }
291             return NO_ERROR;
292         } break;
293         default:
294             return BBinder::onTransact(code, data, reply, flags);
295     }
296 }
297 
298 } // namespace android
299