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 <android/util/ProtoOutputStream.h>
20 #include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
21 #include <hardware/sensors.h>
22 #include <utils/String8.h>
23
24 #include <cinttypes>
25
26 namespace android {
27 namespace SensorServiceUtil {
28
29 const Sensor SensorList::mNonSensor = Sensor("unknown");
30
add(int handle,SensorInterface * si,bool isForDebug,bool isVirtual)31 bool SensorList::add(
32 int handle, SensorInterface* si, bool isForDebug, bool isVirtual) {
33 std::lock_guard<std::mutex> lk(mLock);
34 if (handle == si->getSensor().getHandle() &&
35 mUsedHandle.insert(handle).second) {
36 // will succeed as the mUsedHandle does not have this handle
37 mHandleMap.emplace(handle, Entry(si, isForDebug, isVirtual));
38 return true;
39 }
40 // handle exist already or handle mismatch
41 return false;
42 }
43
remove(int handle)44 bool SensorList::remove(int handle) {
45 std::lock_guard<std::mutex> lk(mLock);
46 auto entry = mHandleMap.find(handle);
47 if (entry != mHandleMap.end()) {
48 mHandleMap.erase(entry);
49 return true;
50 }
51 return false;
52 }
53
getName(int handle) const54 String8 SensorList::getName(int handle) const {
55 return getOne<String8>(
56 handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();},
57 mNonSensor.getName());
58 }
59
getInterface(int handle) const60 sp<SensorInterface> SensorList::getInterface(int handle) const {
61 return getOne<sp<SensorInterface>>(
62 handle, [] (const Entry& e) -> sp<SensorInterface> {return e.si;}, nullptr);
63 }
64
65
isNewHandle(int handle) const66 bool SensorList::isNewHandle(int handle) const {
67 std::lock_guard<std::mutex> lk(mLock);
68 return mUsedHandle.find(handle) == mUsedHandle.end();
69 }
70
getUserSensors() const71 const Vector<Sensor> SensorList::getUserSensors() const {
72 // lock in forEachEntry
73 Vector<Sensor> sensors;
74 forEachEntry(
75 [&sensors] (const Entry& e) -> bool {
76 if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()) {
77 sensors.add(e.si->getSensor());
78 }
79 return true;
80 });
81 return sensors;
82 }
83
getUserDebugSensors() const84 const Vector<Sensor> SensorList::getUserDebugSensors() const {
85 // lock in forEachEntry
86 Vector<Sensor> sensors;
87 forEachEntry(
88 [&sensors] (const Entry& e) -> bool {
89 if (!e.si->getSensor().isDynamicSensor()) {
90 sensors.add(e.si->getSensor());
91 }
92 return true;
93 });
94 return sensors;
95 }
96
getDynamicSensors() const97 const Vector<Sensor> SensorList::getDynamicSensors() const {
98 // lock in forEachEntry
99 Vector<Sensor> sensors;
100 forEachEntry(
101 [&sensors] (const Entry& e) -> bool {
102 if (!e.isForDebug && e.si->getSensor().isDynamicSensor()) {
103 sensors.add(e.si->getSensor());
104 }
105 return true;
106 });
107 return sensors;
108 }
109
getVirtualSensors() const110 const Vector<Sensor> SensorList::getVirtualSensors() const {
111 // lock in forEachEntry
112 Vector<Sensor> sensors;
113 forEachEntry(
114 [&sensors] (const Entry& e) -> bool {
115 if (e.isVirtual) {
116 sensors.add(e.si->getSensor());
117 }
118 return true;
119 });
120 return sensors;
121 }
122
dump() const123 std::string SensorList::dump() const {
124 String8 result;
125
126 forEachSensor([&result] (const Sensor& s) -> bool {
127 result.appendFormat(
128 "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
129 ") | perm: %s | flags: 0x%08x\n",
130 s.getHandle(),
131 s.getName().string(),
132 s.getVendor().string(),
133 s.getVersion(),
134 s.getStringType().string(),
135 s.getType(),
136 s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a",
137 static_cast<int>(s.getFlags()));
138
139 result.append("\t");
140 const int reportingMode = s.getReportingMode();
141 if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
142 result.append("continuous | ");
143 } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
144 result.append("on-change | ");
145 } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
146 result.append("one-shot | ");
147 } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
148 result.append("special-trigger | ");
149 } else {
150 result.append("unknown-mode | ");
151 }
152
153 if (s.getMaxDelay() > 0) {
154 result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
155 } else {
156 result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
157 }
158
159 if (s.getMinDelay() > 0) {
160 result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
161 } else {
162 result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
163 }
164
165 if (s.getFifoMaxEventCount() > 0) {
166 result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
167 s.getFifoMaxEventCount(),
168 s.getFifoReservedEventCount());
169 } else {
170 result.append("no batching | ");
171 }
172
173 if (s.isWakeUpSensor()) {
174 result.appendFormat("wakeUp | ");
175 } else {
176 result.appendFormat("non-wakeUp | ");
177 }
178
179 if (s.isDataInjectionSupported()) {
180 result.appendFormat("data-injection, ");
181 }
182
183 if (s.isDynamicSensor()) {
184 result.appendFormat("dynamic, ");
185 }
186
187 if (s.hasAdditionalInfo()) {
188 result.appendFormat("has-additional-info, ");
189 }
190 result.append("\n");
191
192 if (s.getHighestDirectReportRateLevel() > SENSOR_DIRECT_RATE_STOP) {
193 result.appendFormat("\thighest rate level = %d, support shared mem: ",
194 s.getHighestDirectReportRateLevel());
195 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM)) {
196 result.append("ashmem, ");
197 }
198 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
199 result.append("gralloc, ");
200 }
201 result.append("\n");
202 }
203 return true;
204 });
205 return std::string(result.string());
206 }
207
208 /**
209 * Dump debugging information as android.service.SensorListProto protobuf message using
210 * ProtoOutputStream.
211 *
212 * See proto definition and some notes about ProtoOutputStream in
213 * frameworks/base/core/proto/android/service/sensor_service.proto
214 */
dump(util::ProtoOutputStream * proto) const215 void SensorList::dump(util::ProtoOutputStream* proto) const {
216 using namespace service::SensorListProto;
217 using namespace service::SensorListProto::SensorProto;
218
219 forEachSensor([&proto] (const Sensor& s) -> bool {
220 const uint64_t token = proto->start(SENSORS);
221 proto->write(HANDLE, s.getHandle());
222 proto->write(NAME, std::string(s.getName().string()));
223 proto->write(VENDOR, std::string(s.getVendor().string()));
224 proto->write(VERSION, s.getVersion());
225 proto->write(STRING_TYPE, std::string(s.getStringType().string()));
226 proto->write(TYPE, s.getType());
227 proto->write(REQUIRED_PERMISSION, std::string(s.getRequiredPermission().size() ?
228 s.getRequiredPermission().string() : ""));
229 proto->write(FLAGS, int(s.getFlags()));
230 switch (s.getReportingMode()) {
231 case AREPORTING_MODE_CONTINUOUS:
232 proto->write(REPORTING_MODE, RM_CONTINUOUS);
233 break;
234 case AREPORTING_MODE_ON_CHANGE:
235 proto->write(REPORTING_MODE, RM_ON_CHANGE);
236 break;
237 case AREPORTING_MODE_ONE_SHOT:
238 proto->write(REPORTING_MODE, RM_ONE_SHOT);
239 break;
240 case AREPORTING_MODE_SPECIAL_TRIGGER:
241 proto->write(REPORTING_MODE, RM_SPECIAL_TRIGGER);
242 break;
243 default:
244 proto->write(REPORTING_MODE, RM_UNKNOWN);
245 }
246 proto->write(MAX_DELAY_US, s.getMaxDelay());
247 proto->write(MIN_DELAY_US, s.getMinDelay());
248 proto->write(FIFO_MAX_EVENT_COUNT, int(s.getFifoMaxEventCount()));
249 proto->write(FIFO_RESERVED_EVENT_COUNT, int(s.getFifoReservedEventCount()));
250 proto->write(IS_WAKEUP, s.isWakeUpSensor());
251 proto->write(DATA_INJECTION_SUPPORTED, s.isDataInjectionSupported());
252 proto->write(IS_DYNAMIC, s.isDynamicSensor());
253 proto->write(HAS_ADDITIONAL_INFO, s.hasAdditionalInfo());
254 proto->write(HIGHEST_RATE_LEVEL, s.getHighestDirectReportRateLevel());
255 proto->write(ASHMEM, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM));
256 proto->write(GRALLOC, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC));
257 proto->write(MIN_VALUE, s.getMinValue());
258 proto->write(MAX_VALUE, s.getMaxValue());
259 proto->write(RESOLUTION, s.getResolution());
260 proto->write(POWER_USAGE, s.getPowerUsage());
261 proto->end(token);
262 return true;
263 });
264 }
265
~SensorList()266 SensorList::~SensorList() {
267 }
268
269 } // namespace SensorServiceUtil
270 } // namespace android
271
272