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 "SensorList.h"
18
19#include <hardware/sensors.h>
20#include <utils/String8.h>
21
22#include <cinttypes>
23
24namespace android {
25namespace SensorServiceUtil {
26
27const Sensor SensorList::mNonSensor = Sensor("unknown");
28
29bool SensorList::add(
30        int handle, SensorInterface* si, bool isForDebug, bool isVirtual) {
31    std::lock_guard<std::mutex> lk(mLock);
32    if (handle == si->getSensor().getHandle() &&
33        mUsedHandle.insert(handle).second) {
34        // will succeed as the mUsedHandle does not have this handle
35        mHandleMap.emplace(handle, Entry(si, isForDebug, isVirtual));
36        return true;
37    }
38    // handle exist already or handle mismatch
39    return false;
40}
41
42bool SensorList::remove(int handle) {
43    std::lock_guard<std::mutex> lk(mLock);
44    auto entry = mHandleMap.find(handle);
45    if (entry != mHandleMap.end()) {
46        mHandleMap.erase(entry);
47        return true;
48    }
49    return false;
50}
51
52String8 SensorList::getName(int handle) const {
53    return getOne<String8>(
54            handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();},
55            mNonSensor.getName());
56}
57
58sp<SensorInterface> SensorList::getInterface(int handle) const {
59    return getOne<sp<SensorInterface>>(
60            handle, [] (const Entry& e) -> sp<SensorInterface> {return e.si;}, nullptr);
61}
62
63
64bool SensorList::isNewHandle(int handle) const {
65    std::lock_guard<std::mutex> lk(mLock);
66    return mUsedHandle.find(handle) == mUsedHandle.end();
67}
68
69const Vector<Sensor> SensorList::getUserSensors() const {
70    // lock in forEachEntry
71    Vector<Sensor> sensors;
72    forEachEntry(
73            [&sensors] (const Entry& e) -> bool {
74                if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()) {
75                    sensors.add(e.si->getSensor());
76                }
77                return true;
78            });
79    return sensors;
80}
81
82const Vector<Sensor> SensorList::getUserDebugSensors() const {
83    // lock in forEachEntry
84    Vector<Sensor> sensors;
85    forEachEntry(
86            [&sensors] (const Entry& e) -> bool {
87                if (!e.si->getSensor().isDynamicSensor()) {
88                    sensors.add(e.si->getSensor());
89                }
90                return true;
91            });
92    return sensors;
93}
94
95const Vector<Sensor> SensorList::getDynamicSensors() const {
96    // lock in forEachEntry
97    Vector<Sensor> sensors;
98    forEachEntry(
99            [&sensors] (const Entry& e) -> bool {
100                if (!e.isForDebug && e.si->getSensor().isDynamicSensor()) {
101                    sensors.add(e.si->getSensor());
102                }
103                return true;
104            });
105    return sensors;
106}
107
108const Vector<Sensor> SensorList::getVirtualSensors() const {
109    // lock in forEachEntry
110    Vector<Sensor> sensors;
111    forEachEntry(
112            [&sensors] (const Entry& e) -> bool {
113                if (e.isVirtual) {
114                    sensors.add(e.si->getSensor());
115                }
116                return true;
117            });
118    return sensors;
119}
120
121std::string SensorList::dump() const {
122    String8 result;
123
124    forEachSensor([&result] (const Sensor& s) -> bool {
125            result.appendFormat(
126                    "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
127                        ") | perm: %s\n",
128                    s.getHandle(),
129                    s.getName().string(),
130                    s.getVendor().string(),
131                    s.getVersion(),
132                    s.getStringType().string(),
133                    s.getType(),
134                    s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a");
135
136            result.append("\t");
137            const int reportingMode = s.getReportingMode();
138            if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
139                result.append("continuous | ");
140            } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
141                result.append("on-change | ");
142            } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
143                result.append("one-shot | ");
144            } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
145                result.append("special-trigger | ");
146            } else {
147                result.append("unknown-mode | ");
148            }
149
150            if (s.getMaxDelay() > 0) {
151                result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
152            } else {
153                result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
154            }
155
156            if (s.getMinDelay() > 0) {
157                result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
158            } else {
159                result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
160            }
161
162            if (s.getFifoMaxEventCount() > 0) {
163                result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
164                        s.getFifoMaxEventCount(),
165                        s.getFifoReservedEventCount());
166            } else {
167                result.append("no batching | ");
168            }
169
170            if (s.isWakeUpSensor()) {
171                result.appendFormat("wakeUp | ");
172            } else {
173                result.appendFormat("non-wakeUp | ");
174            }
175
176            if (s.isDynamicSensor()) {
177                result.appendFormat("dynamic, ");
178            }
179            if (s.hasAdditionalInfo()) {
180                result.appendFormat("has-additional-info, ");
181            }
182            result.append("\n");
183
184            if (s.getHighestDirectReportRateLevel() > SENSOR_DIRECT_RATE_STOP) {
185                result.appendFormat("\thighest rate level = %d, support shared mem: ",
186                        s.getHighestDirectReportRateLevel());
187                if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM)) {
188                    result.append("ashmem, ");
189                }
190                if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
191                    result.append("gralloc, ");
192                }
193                result.appendFormat("flag =0x%08x", static_cast<int>(s.getFlags()));
194                result.append("\n");
195            }
196            return true;
197        });
198    return std::string(result.string());
199}
200
201SensorList::~SensorList() {
202}
203
204} // namespace SensorServiceUtil
205} // namespace android
206
207