blob: 3b800de2f30b66e0413358498446b6b15e7b8b3a [file] [log] [blame]
Aurimas Liutikas88c7ff12023-08-10 12:42:26 -07001/*
2 * Copyright (C) 2019 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.server.soundtrigger_middleware;
18
19import android.annotation.NonNull;
20import android.media.soundtrigger_middleware.ISoundTriggerCallback;
21import android.media.soundtrigger_middleware.ISoundTriggerModule;
22import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
23import android.util.Log;
24
25import java.util.ArrayList;
26import java.util.List;
27
28/**
29 * This is an implementation of the ISoundTriggerMiddlewareService interface.
30 * <p>
31 * <b>Important conventions:</b>
32 * <ul>
33 * <li>Correct usage is assumed. This implementation does not attempt to gracefully handle invalid
34 * usage, and such usage will result in undefined behavior. If this service is to be offered to an
35 * untrusted client, it must be wrapped with input and state validation.
36 * <li>There is no binder instance associated with this implementation. Do not call asBinder().
37 * <li>The implementation may throw a {@link RecoverableException} to indicate non-fatal,
38 * recoverable faults. The error code would one of the
39 * {@link android.media.soundtrigger.Status}
40 * constants. Any other exception thrown should be regarded as a bug in the implementation or one
41 * of its dependencies (assuming correct usage).
42 * <li>The implementation is designed for testibility by featuring dependency injection (the
43 * underlying HAL driver instances are passed to the ctor) and by minimizing dependencies on
44 * Android runtime.
45 * <li>The implementation is thread-safe.
46 * </ul>
47 *
48 * @hide
49 */
50public class SoundTriggerMiddlewareImpl implements ISoundTriggerMiddlewareInternal {
51 static private final String TAG = "SoundTriggerMiddlewareImpl";
52 private final SoundTriggerModule[] mModules;
53
54 /**
55 * Interface to the audio system, which can allocate capture session handles.
56 * SoundTrigger uses those sessions in order to associate a recognition session with an optional
57 * capture from the same device that triggered the recognition.
58 */
59 public static abstract class AudioSessionProvider {
60 public static final class AudioSession {
61 final int mSessionHandle;
62 final int mIoHandle;
63 final int mDeviceHandle;
64
65 AudioSession(int sessionHandle, int ioHandle, int deviceHandle) {
66 mSessionHandle = sessionHandle;
67 mIoHandle = ioHandle;
68 mDeviceHandle = deviceHandle;
69 }
70 }
71
72 public abstract AudioSession acquireSession();
73
74 public abstract void releaseSession(int sessionHandle);
75 }
76
77 /**
78 * Constructor - gets an array of HAL driver factories.
79 */
80 public SoundTriggerMiddlewareImpl(@NonNull HalFactory[] halFactories,
81 @NonNull AudioSessionProvider audioSessionProvider) {
82 List<SoundTriggerModule> modules = new ArrayList<>(halFactories.length);
83
84 for (HalFactory halFactory : halFactories) {
85 try {
86 modules.add(new SoundTriggerModule(halFactory, audioSessionProvider));
87 } catch (Exception e) {
88 Log.e(TAG, "Failed to add a SoundTriggerModule instance", e);
89 }
90 }
91
92 mModules = modules.toArray(new SoundTriggerModule[0]);
93 }
94
95 /**
96 * Convenience constructor - gets a single HAL factory.
97 */
98 public SoundTriggerMiddlewareImpl(@NonNull HalFactory factory,
99 @NonNull AudioSessionProvider audioSessionProvider) {
100 this(new HalFactory[]{factory}, audioSessionProvider);
101 }
102
103 @Override
104 public @NonNull
105 SoundTriggerModuleDescriptor[] listModules() {
106 SoundTriggerModuleDescriptor[] result = new SoundTriggerModuleDescriptor[mModules.length];
107
108 for (int i = 0; i < mModules.length; ++i) {
109 SoundTriggerModuleDescriptor desc = new SoundTriggerModuleDescriptor();
110 desc.handle = i;
111 desc.properties = mModules[i].getProperties();
112 result[i] = desc;
113 }
114 return result;
115 }
116
117 @Override
118 public @NonNull
119 ISoundTriggerModule attach(int handle, @NonNull ISoundTriggerCallback callback,
120 boolean isTrusted) {
121 return mModules[handle].attach(callback);
122 }
123}