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
43class BpSoundTriggerHwService: public BpInterface<ISoundTriggerHwService>
44{
45public:
46    BpSoundTriggerHwService(const sp<IBinder>& impl)
47        : BpInterface<ISoundTriggerHwService>(impl)
48    {
49    }
50
51    virtual status_t listModules(struct sound_trigger_module_descriptor *modules,
52                                 uint32_t *numModules)
53    {
54        if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
55            return BAD_VALUE;
56        }
57        Parcel data, reply;
58        data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
59        unsigned int numModulesReq = (modules == NULL) ? 0 : *numModules;
60        data.writeInt32(numModulesReq);
61        status_t status = remote()->transact(LIST_MODULES, data, &reply);
62        if (status == NO_ERROR) {
63            status = (status_t)reply.readInt32();
64            *numModules = (unsigned int)reply.readInt32();
65        }
66        ALOGV("listModules() status %d got *numModules %d", status, *numModules);
67        if (status == NO_ERROR) {
68            if (numModulesReq > *numModules) {
69                numModulesReq = *numModules;
70            }
71            if (numModulesReq > 0) {
72                reply.read(modules, numModulesReq * sizeof(struct sound_trigger_module_descriptor));
73            }
74        }
75        return status;
76    }
77
78    virtual status_t attach(const sound_trigger_module_handle_t handle,
79                            const sp<ISoundTriggerClient>& client,
80                            sp<ISoundTrigger>& module)
81    {
82        Parcel data, reply;
83        data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
84        data.write(&handle, sizeof(sound_trigger_module_handle_t));
85        data.writeStrongBinder(client->asBinder());
86        remote()->transact(ATTACH, data, &reply);
87        status_t status = reply.readInt32();
88        if (reply.readInt32() != 0) {
89            module = interface_cast<ISoundTrigger>(reply.readStrongBinder());
90        }
91        return status;
92    }
93
94    virtual status_t setCaptureState(bool active)
95    {
96        Parcel data, reply;
97        data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
98        data.writeInt32(active);
99        status_t status = remote()->transact(SET_CAPTURE_STATE, data, &reply);
100        if (status == NO_ERROR) {
101            status = reply.readInt32();
102        }
103        return status;
104    }
105
106};
107
108IMPLEMENT_META_INTERFACE(SoundTriggerHwService, "android.hardware.ISoundTriggerHwService");
109
110// ----------------------------------------------------------------------
111
112status_t BnSoundTriggerHwService::onTransact(
113    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
114{
115    switch(code) {
116        case LIST_MODULES: {
117            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
118            unsigned int numModulesReq = data.readInt32();
119            unsigned int numModules = numModulesReq;
120            struct sound_trigger_module_descriptor *modules =
121                    (struct sound_trigger_module_descriptor *)calloc(numModulesReq,
122                                                   sizeof(struct sound_trigger_module_descriptor));
123            status_t status = listModules(modules, &numModules);
124            reply->writeInt32(status);
125            reply->writeInt32(numModules);
126            ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
127
128            if (status == NO_ERROR) {
129                if (numModulesReq > numModules) {
130                    numModulesReq = numModules;
131                }
132                reply->write(modules,
133                             numModulesReq * sizeof(struct sound_trigger_module_descriptor));
134            }
135            free(modules);
136            return NO_ERROR;
137        }
138
139        case ATTACH: {
140            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
141            sound_trigger_module_handle_t handle;
142            data.read(&handle, sizeof(sound_trigger_module_handle_t));
143            sp<ISoundTriggerClient> client =
144                    interface_cast<ISoundTriggerClient>(data.readStrongBinder());
145            sp<ISoundTrigger> module;
146            status_t status = attach(handle, client, module);
147            reply->writeInt32(status);
148            if (module != 0) {
149                reply->writeInt32(1);
150                reply->writeStrongBinder(module->asBinder());
151            } else {
152                reply->writeInt32(0);
153            }
154            return NO_ERROR;
155        } break;
156
157        case SET_CAPTURE_STATE: {
158            CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
159            reply->writeInt32(setCaptureState((bool)data.readInt32()));
160            return NO_ERROR;
161        } break;
162
163        default:
164            return BBinder::onTransact(code, data, reply, flags);
165    }
166}
167
168// ----------------------------------------------------------------------------
169
170}; // namespace android
171