1/*
2 * Copyright (C) 2016 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
17#include "SensorDevice.h"
18#include "SensorDirectConnection.h"
19#include <hardware/sensors.h>
20
21#define UNUSED(x) (void)(x)
22
23namespace android {
24
25SensorService::SensorDirectConnection::SensorDirectConnection(const sp<SensorService>& service,
26        uid_t uid, const sensors_direct_mem_t *mem, int32_t halChannelHandle,
27        const String16& opPackageName)
28        : mService(service), mUid(uid), mMem(*mem),
29        mHalChannelHandle(halChannelHandle),
30        mOpPackageName(opPackageName), mDestroyed(false) {
31    ALOGD_IF(DEBUG_CONNECTIONS, "Created SensorDirectConnection");
32}
33
34SensorService::SensorDirectConnection::~SensorDirectConnection() {
35    ALOGD_IF(DEBUG_CONNECTIONS, "~SensorDirectConnection %p", this);
36    destroy();
37}
38
39void SensorService::SensorDirectConnection::destroy() {
40    Mutex::Autolock _l(mDestroyLock);
41    // destroy once only
42    if (mDestroyed) {
43        return;
44    }
45
46    stopAll();
47    mService->cleanupConnection(this);
48    if (mMem.handle != nullptr) {
49        native_handle_close(mMem.handle);
50        native_handle_delete(const_cast<struct native_handle*>(mMem.handle));
51    }
52    mDestroyed = true;
53}
54
55void SensorService::SensorDirectConnection::onFirstRef() {
56}
57
58void SensorService::SensorDirectConnection::dump(String8& result) const {
59    Mutex::Autolock _l(mConnectionLock);
60    result.appendFormat("\tPackage %s, HAL channel handle %d, total sensor activated %zu\n",
61            String8(mOpPackageName).string(), getHalChannelHandle(), mActivated.size());
62    for (auto &i : mActivated) {
63        result.appendFormat("\t\tSensor %#08x, rate %d\n", i.first, i.second);
64    }
65}
66
67sp<BitTube> SensorService::SensorDirectConnection::getSensorChannel() const {
68    return nullptr;
69}
70
71status_t SensorService::SensorDirectConnection::enableDisable(
72        int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
73        int reservedFlags) {
74    // SensorDirectConnection does not support enableDisable, parameters not used
75    UNUSED(handle);
76    UNUSED(enabled);
77    UNUSED(samplingPeriodNs);
78    UNUSED(maxBatchReportLatencyNs);
79    UNUSED(reservedFlags);
80    return INVALID_OPERATION;
81}
82
83status_t SensorService::SensorDirectConnection::setEventRate(
84        int handle, nsecs_t samplingPeriodNs) {
85    // SensorDirectConnection does not support setEventRate, parameters not used
86    UNUSED(handle);
87    UNUSED(samplingPeriodNs);
88    return INVALID_OPERATION;
89}
90
91status_t SensorService::SensorDirectConnection::flush() {
92    // SensorDirectConnection does not support flush
93    return INVALID_OPERATION;
94}
95
96int32_t SensorService::SensorDirectConnection::configureChannel(int handle, int rateLevel) {
97
98    if (handle == -1 && rateLevel == SENSOR_DIRECT_RATE_STOP) {
99        stopAll();
100        return NO_ERROR;
101    }
102
103    if (mService->isOperationRestricted(mOpPackageName)) {
104        return PERMISSION_DENIED;
105    }
106
107    sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
108    if (si == nullptr) {
109        return NAME_NOT_FOUND;
110    }
111
112    const Sensor& s = si->getSensor();
113    if (!SensorService::canAccessSensor(s, "config direct channel", mOpPackageName)) {
114        return PERMISSION_DENIED;
115    }
116
117    if (s.getHighestDirectReportRateLevel() == 0
118            || rateLevel > s.getHighestDirectReportRateLevel()
119            || !s.isDirectChannelTypeSupported(mMem.type)) {
120        return INVALID_OPERATION;
121    }
122
123    struct sensors_direct_cfg_t config = {
124        .rate_level = rateLevel
125    };
126
127    Mutex::Autolock _l(mConnectionLock);
128    SensorDevice& dev(SensorDevice::getInstance());
129    int ret = dev.configureDirectChannel(handle, getHalChannelHandle(), &config);
130
131    if (rateLevel == SENSOR_DIRECT_RATE_STOP) {
132        if (ret == NO_ERROR) {
133            mActivated.erase(handle);
134        } else if (ret > 0) {
135            ret = UNKNOWN_ERROR;
136        }
137    } else {
138        if (ret > 0) {
139            mActivated[handle] = rateLevel;
140        }
141    }
142
143    return ret;
144}
145
146void SensorService::SensorDirectConnection::stopAll(bool backupRecord) {
147
148    struct sensors_direct_cfg_t config = {
149        .rate_level = SENSOR_DIRECT_RATE_STOP
150    };
151
152    Mutex::Autolock _l(mConnectionLock);
153    SensorDevice& dev(SensorDevice::getInstance());
154    for (auto &i : mActivated) {
155        dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
156    }
157
158    if (backupRecord && mActivatedBackup.empty()) {
159        mActivatedBackup = mActivated;
160    }
161    mActivated.clear();
162}
163
164void SensorService::SensorDirectConnection::recoverAll() {
165    stopAll(false);
166
167    Mutex::Autolock _l(mConnectionLock);
168    SensorDevice& dev(SensorDevice::getInstance());
169
170    // recover list of report from backup
171    mActivated = mActivatedBackup;
172    mActivatedBackup.clear();
173
174    // re-enable them
175    for (auto &i : mActivated) {
176        struct sensors_direct_cfg_t config = {
177            .rate_level = i.second
178        };
179        dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
180    }
181}
182
183int32_t SensorService::SensorDirectConnection::getHalChannelHandle() const {
184    return mHalChannelHandle;
185}
186
187bool SensorService::SensorDirectConnection::isEquivalent(const sensors_direct_mem_t *mem) const {
188    bool ret = false;
189
190    if (mMem.type == mem->type) {
191        switch (mMem.type) {
192            case SENSOR_DIRECT_MEM_TYPE_ASHMEM: {
193                // there is no known method to test if two ashmem fds are equivalent besides
194                // trivially comparing the fd values (ino number from fstat() are always the
195                // same, pointing to "/dev/ashmem").
196                int fd1 = mMem.handle->data[0];
197                int fd2 = mem->handle->data[0];
198                ret = (fd1 == fd2);
199                break;
200            }
201            case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
202                // there is no known method to test if two gralloc handle are equivalent
203                ret = false;
204                break;
205            default:
206                // should never happen
207                ALOGE("Unexpected mem type %d", mMem.type);
208                ret = true;
209                break;
210        }
211    }
212    return ret;
213}
214
215} // namespace android
216
217