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
35namespace android {
36
37enum {
38    LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
39    ATTACH,
40    SET_CAPTURE_STATE,
41};
42
43#define MAX_ITEMS_PER_LIST 1024
44
45class BpSoundTriggerHwService: public BpInterface<ISoundTriggerHwService>
46{
47public:
48    BpSoundTriggerHwService(const sp<IBinder>& impl)
49        : BpInterface<ISoundTriggerHwService>(impl)
50    {
51    }
52
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
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        status_t status = remote()->transact(ATTACH, data, &reply);
89        if (status != NO_ERROR) {
90            return status;
91        }
92        status = reply.readInt32();
93        if (reply.readInt32() != 0) {
94            module = interface_cast<ISoundTrigger>(reply.readStrongBinder());
95        }
96        return status;
97    }
98
99    virtual status_t setCaptureState(bool active)
100    {
101        Parcel data, reply;
102        data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
103        data.writeInt32(active);
104        status_t status = remote()->transact(SET_CAPTURE_STATE, data, &reply);
105        if (status == NO_ERROR) {
106            status = reply.readInt32();
107        }
108        return status;
109    }
110
111};
112
113IMPLEMENT_META_INTERFACE(SoundTriggerHwService, "android.hardware.ISoundTriggerHwService");
114
115// ----------------------------------------------------------------------
116
117status_t BnSoundTriggerHwService::onTransact(
118    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
119{
120    switch(code) {
121        case LIST_MODULES: {
122            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
123            unsigned int numModulesReq = data.readInt32();
124            if (numModulesReq > MAX_ITEMS_PER_LIST) {
125                numModulesReq = MAX_ITEMS_PER_LIST;
126            }
127            unsigned int numModules = numModulesReq;
128            struct sound_trigger_module_descriptor *modules =
129                    (struct sound_trigger_module_descriptor *)calloc(numModulesReq,
130                                                   sizeof(struct sound_trigger_module_descriptor));
131            if (modules == NULL) {
132                reply->writeInt32(NO_MEMORY);
133                reply->writeInt32(0);
134                return NO_ERROR;
135            }
136            status_t status = listModules(modules, &numModules);
137            reply->writeInt32(status);
138            reply->writeInt32(numModules);
139            ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
140
141            if (status == NO_ERROR) {
142                if (numModulesReq > numModules) {
143                    numModulesReq = numModules;
144                }
145                reply->write(modules,
146                             numModulesReq * sizeof(struct sound_trigger_module_descriptor));
147            }
148            free(modules);
149            return NO_ERROR;
150        }
151
152        case ATTACH: {
153            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
154            sound_trigger_module_handle_t handle;
155            data.read(&handle, sizeof(sound_trigger_module_handle_t));
156            sp<ISoundTriggerClient> client =
157                    interface_cast<ISoundTriggerClient>(data.readStrongBinder());
158            sp<ISoundTrigger> module;
159            status_t status = attach(handle, client, module);
160            reply->writeInt32(status);
161            if (module != 0) {
162                reply->writeInt32(1);
163                reply->writeStrongBinder(IInterface::asBinder(module));
164            } else {
165                reply->writeInt32(0);
166            }
167            return NO_ERROR;
168        } break;
169
170        case SET_CAPTURE_STATE: {
171            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
172            reply->writeInt32(setCaptureState((bool)data.readInt32()));
173            return NO_ERROR;
174        } break;
175
176        default:
177            return BBinder::onTransact(code, data, reply, flags);
178    }
179}
180
181// ----------------------------------------------------------------------------
182
183}; // namespace android
184