1 /*
2 **
3 ** Copyright 2014, 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 "BpSoundTriggerHwService"
19 //#define LOG_NDEBUG 0
20
21 #include <utils/Log.h>
22 #include <utils/Errors.h>
23
24 #include <stdint.h>
25 #include <sys/types.h>
26 #include <binder/IMemory.h>
27 #include <binder/Parcel.h>
28 #include <binder/IPCThreadState.h>
29 #include <binder/IServiceManager.h>
30
31 #include <soundtrigger/ISoundTriggerHwService.h>
32 #include <soundtrigger/ISoundTrigger.h>
33 #include <soundtrigger/ISoundTriggerClient.h>
34
35 namespace android {
36
37 enum {
38 LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
39 ATTACH,
40 SET_CAPTURE_STATE,
41 };
42
43 #define MAX_ITEMS_PER_LIST 1024
44
45 class BpSoundTriggerHwService: public BpInterface<ISoundTriggerHwService>
46 {
47 public:
BpSoundTriggerHwService(const sp<IBinder> & impl)48 BpSoundTriggerHwService(const sp<IBinder>& impl)
49 : BpInterface<ISoundTriggerHwService>(impl)
50 {
51 }
52
listModules(struct sound_trigger_module_descriptor * modules,uint32_t * numModules)53 virtual status_t listModules(struct sound_trigger_module_descriptor *modules,
54 uint32_t *numModules)
55 {
56 if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
57 return BAD_VALUE;
58 }
59 Parcel data, reply;
60 data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
61 unsigned int numModulesReq = (modules == NULL) ? 0 : *numModules;
62 data.writeInt32(numModulesReq);
63 status_t status = remote()->transact(LIST_MODULES, data, &reply);
64 if (status == NO_ERROR) {
65 status = (status_t)reply.readInt32();
66 *numModules = (unsigned int)reply.readInt32();
67 }
68 ALOGV("listModules() status %d got *numModules %d", status, *numModules);
69 if (status == NO_ERROR) {
70 if (numModulesReq > *numModules) {
71 numModulesReq = *numModules;
72 }
73 if (numModulesReq > 0) {
74 reply.read(modules, numModulesReq * sizeof(struct sound_trigger_module_descriptor));
75 }
76 }
77 return status;
78 }
79
attach(const sound_trigger_module_handle_t handle,const sp<ISoundTriggerClient> & client,sp<ISoundTrigger> & module)80 virtual status_t attach(const sound_trigger_module_handle_t handle,
81 const sp<ISoundTriggerClient>& client,
82 sp<ISoundTrigger>& module)
83 {
84 Parcel data, reply;
85 data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
86 data.write(&handle, sizeof(sound_trigger_module_handle_t));
87 data.writeStrongBinder(IInterface::asBinder(client));
88 remote()->transact(ATTACH, data, &reply);
89 status_t status = reply.readInt32();
90 if (reply.readInt32() != 0) {
91 module = interface_cast<ISoundTrigger>(reply.readStrongBinder());
92 }
93 return status;
94 }
95
setCaptureState(bool active)96 virtual status_t setCaptureState(bool active)
97 {
98 Parcel data, reply;
99 data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
100 data.writeInt32(active);
101 status_t status = remote()->transact(SET_CAPTURE_STATE, data, &reply);
102 if (status == NO_ERROR) {
103 status = reply.readInt32();
104 }
105 return status;
106 }
107
108 };
109
110 IMPLEMENT_META_INTERFACE(SoundTriggerHwService, "android.hardware.ISoundTriggerHwService");
111
112 // ----------------------------------------------------------------------
113
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)114 status_t BnSoundTriggerHwService::onTransact(
115 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
116 {
117 switch(code) {
118 case LIST_MODULES: {
119 CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
120 unsigned int numModulesReq = data.readInt32();
121 if (numModulesReq > MAX_ITEMS_PER_LIST) {
122 numModulesReq = MAX_ITEMS_PER_LIST;
123 }
124 unsigned int numModules = numModulesReq;
125 struct sound_trigger_module_descriptor *modules =
126 (struct sound_trigger_module_descriptor *)calloc(numModulesReq,
127 sizeof(struct sound_trigger_module_descriptor));
128 if (modules == NULL) {
129 reply->writeInt32(NO_MEMORY);
130 reply->writeInt32(0);
131 return NO_ERROR;
132 }
133 status_t status = listModules(modules, &numModules);
134 reply->writeInt32(status);
135 reply->writeInt32(numModules);
136 ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
137
138 if (status == NO_ERROR) {
139 if (numModulesReq > numModules) {
140 numModulesReq = numModules;
141 }
142 reply->write(modules,
143 numModulesReq * sizeof(struct sound_trigger_module_descriptor));
144 }
145 free(modules);
146 return NO_ERROR;
147 }
148
149 case ATTACH: {
150 CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
151 sound_trigger_module_handle_t handle;
152 data.read(&handle, sizeof(sound_trigger_module_handle_t));
153 sp<ISoundTriggerClient> client =
154 interface_cast<ISoundTriggerClient>(data.readStrongBinder());
155 sp<ISoundTrigger> module;
156 status_t status = attach(handle, client, module);
157 reply->writeInt32(status);
158 if (module != 0) {
159 reply->writeInt32(1);
160 reply->writeStrongBinder(IInterface::asBinder(module));
161 } else {
162 reply->writeInt32(0);
163 }
164 return NO_ERROR;
165 } break;
166
167 case SET_CAPTURE_STATE: {
168 CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
169 reply->writeInt32(setCaptureState((bool)data.readInt32()));
170 return NO_ERROR;
171 } break;
172
173 default:
174 return BBinder::onTransact(code, data, reply, flags);
175 }
176 }
177
178 // ----------------------------------------------------------------------------
179
180 }; // namespace android
181