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,std::shared_ptr<SensorInterface> si,bool isForDebug,bool isVirtual,int deviceId)31 bool SensorList::add(int handle, std::shared_ptr<SensorInterface> si, bool isForDebug,
32 bool isVirtual, int deviceId) {
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(std::move(si), isForDebug, isVirtual, deviceId));
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
getStringType(int handle) const60 String8 SensorList::getStringType(int handle) const {
61 return getOne<String8>(
62 handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getStringType();},
63 mNonSensor.getStringType());
64 }
65
getInterface(int handle) const66 std::shared_ptr<SensorInterface> SensorList::getInterface(int handle) const {
67 return getOne<std::shared_ptr<SensorInterface>>(
68 handle, [] (const Entry& e) -> std::shared_ptr<SensorInterface> {return e.si;},
69 nullptr);
70 }
71
isNewHandle(int handle) const72 bool SensorList::isNewHandle(int handle) const {
73 std::lock_guard<std::mutex> lk(mLock);
74 return mUsedHandle.find(handle) == mUsedHandle.end();
75 }
76
getUserSensors() const77 const Vector<Sensor> SensorList::getUserSensors() const {
78 // lock in forEachEntry
79 Vector<Sensor> sensors;
80 forEachEntry(
81 [&sensors] (const Entry& e) -> bool {
82 if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()
83 && e.deviceId == RuntimeSensor::DEFAULT_DEVICE_ID) {
84 sensors.add(e.si->getSensor());
85 }
86 return true;
87 });
88 return sensors;
89 }
90
getUserDebugSensors() const91 const Vector<Sensor> SensorList::getUserDebugSensors() const {
92 // lock in forEachEntry
93 Vector<Sensor> sensors;
94 forEachEntry(
95 [&sensors] (const Entry& e) -> bool {
96 if (!e.si->getSensor().isDynamicSensor()
97 && e.deviceId == RuntimeSensor::DEFAULT_DEVICE_ID) {
98 sensors.add(e.si->getSensor());
99 }
100 return true;
101 });
102 return sensors;
103 }
104
getDynamicSensors() const105 const Vector<Sensor> SensorList::getDynamicSensors() const {
106 // lock in forEachEntry
107 Vector<Sensor> sensors;
108 forEachEntry(
109 [&sensors] (const Entry& e) -> bool {
110 if (!e.isForDebug && e.si->getSensor().isDynamicSensor()
111 && e.deviceId == RuntimeSensor::DEFAULT_DEVICE_ID) {
112 sensors.add(e.si->getSensor());
113 }
114 return true;
115 });
116 return sensors;
117 }
118
getVirtualSensors() const119 const Vector<Sensor> SensorList::getVirtualSensors() const {
120 // lock in forEachEntry
121 Vector<Sensor> sensors;
122 forEachEntry(
123 [&sensors] (const Entry& e) -> bool {
124 if (e.isVirtual && e.deviceId == RuntimeSensor::DEFAULT_DEVICE_ID) {
125 sensors.add(e.si->getSensor());
126 }
127 return true;
128 });
129 return sensors;
130 }
131
getRuntimeSensors(int deviceId) const132 const Vector<Sensor> SensorList::getRuntimeSensors(int deviceId) const {
133 // lock in forEachEntry
134 Vector<Sensor> sensors;
135 forEachEntry(
136 [&sensors, deviceId] (const Entry& e) -> bool {
137 if (!e.isForDebug && e.deviceId == deviceId) {
138 sensors.add(e.si->getSensor());
139 }
140 return true;
141 });
142 return sensors;
143 }
144
dump() const145 std::string SensorList::dump() const {
146 String8 result;
147
148 forEachSensor([&result] (const Sensor& s) -> bool {
149 result.appendFormat(
150 "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
151 ") | perm: %s | flags: 0x%08x\n",
152 s.getHandle(),
153 s.getName().c_str(),
154 s.getVendor().c_str(),
155 s.getVersion(),
156 s.getStringType().c_str(),
157 s.getType(),
158 s.getRequiredPermission().size() ? s.getRequiredPermission().c_str() : "n/a",
159 static_cast<int>(s.getFlags()));
160
161 result.append("\t");
162 const int reportingMode = s.getReportingMode();
163 if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
164 result.append("continuous | ");
165 } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
166 result.append("on-change | ");
167 } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
168 result.append("one-shot | ");
169 } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
170 result.append("special-trigger | ");
171 } else {
172 result.append("unknown-mode | ");
173 }
174
175 if (s.getMaxDelay() > 0) {
176 result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
177 } else {
178 result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
179 }
180
181 if (s.getMinDelay() > 0) {
182 result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
183 } else {
184 result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
185 }
186
187 if (s.getFifoMaxEventCount() > 0) {
188 result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
189 s.getFifoMaxEventCount(),
190 s.getFifoReservedEventCount());
191 } else {
192 result.append("no batching | ");
193 }
194
195 if (s.isWakeUpSensor()) {
196 result.appendFormat("wakeUp | ");
197 } else {
198 result.appendFormat("non-wakeUp | ");
199 }
200
201 if (s.isDataInjectionSupported()) {
202 result.appendFormat("data-injection, ");
203 }
204
205 if (s.isDynamicSensor()) {
206 result.appendFormat("dynamic, ");
207 }
208
209 if (s.hasAdditionalInfo()) {
210 result.appendFormat("has-additional-info, ");
211 }
212 result.append("\n");
213
214 if (s.getHighestDirectReportRateLevel() > SENSOR_DIRECT_RATE_STOP) {
215 result.appendFormat("\thighest rate level = %d, support shared mem: ",
216 s.getHighestDirectReportRateLevel());
217 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM)) {
218 result.append("ashmem, ");
219 }
220 if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
221 result.append("gralloc, ");
222 }
223 result.append("\n");
224 }
225 return true;
226 });
227 return std::string(result.c_str());
228 }
229
230 /**
231 * Dump debugging information as android.service.SensorListProto protobuf message using
232 * ProtoOutputStream.
233 *
234 * See proto definition and some notes about ProtoOutputStream in
235 * frameworks/base/core/proto/android/service/sensor_service.proto
236 */
dump(util::ProtoOutputStream * proto) const237 void SensorList::dump(util::ProtoOutputStream* proto) const {
238 using namespace service::SensorListProto;
239 using namespace service::SensorListProto::SensorProto;
240
241 forEachSensor([&proto] (const Sensor& s) -> bool {
242 const uint64_t token = proto->start(SENSORS);
243 proto->write(HANDLE, s.getHandle());
244 proto->write(NAME, std::string(s.getName().c_str()));
245 proto->write(VENDOR, std::string(s.getVendor().c_str()));
246 proto->write(VERSION, s.getVersion());
247 proto->write(STRING_TYPE, std::string(s.getStringType().c_str()));
248 proto->write(TYPE, s.getType());
249 proto->write(REQUIRED_PERMISSION, std::string(s.getRequiredPermission().size() ?
250 s.getRequiredPermission().c_str() : ""));
251 proto->write(FLAGS, int(s.getFlags()));
252 switch (s.getReportingMode()) {
253 case AREPORTING_MODE_CONTINUOUS:
254 proto->write(REPORTING_MODE, RM_CONTINUOUS);
255 break;
256 case AREPORTING_MODE_ON_CHANGE:
257 proto->write(REPORTING_MODE, RM_ON_CHANGE);
258 break;
259 case AREPORTING_MODE_ONE_SHOT:
260 proto->write(REPORTING_MODE, RM_ONE_SHOT);
261 break;
262 case AREPORTING_MODE_SPECIAL_TRIGGER:
263 proto->write(REPORTING_MODE, RM_SPECIAL_TRIGGER);
264 break;
265 default:
266 proto->write(REPORTING_MODE, RM_UNKNOWN);
267 }
268 proto->write(MAX_DELAY_US, s.getMaxDelay());
269 proto->write(MIN_DELAY_US, s.getMinDelay());
270 proto->write(FIFO_MAX_EVENT_COUNT, int(s.getFifoMaxEventCount()));
271 proto->write(FIFO_RESERVED_EVENT_COUNT, int(s.getFifoReservedEventCount()));
272 proto->write(IS_WAKEUP, s.isWakeUpSensor());
273 proto->write(DATA_INJECTION_SUPPORTED, s.isDataInjectionSupported());
274 proto->write(IS_DYNAMIC, s.isDynamicSensor());
275 proto->write(HAS_ADDITIONAL_INFO, s.hasAdditionalInfo());
276 proto->write(HIGHEST_RATE_LEVEL, s.getHighestDirectReportRateLevel());
277 proto->write(ASHMEM, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM));
278 proto->write(GRALLOC, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC));
279 proto->write(MIN_VALUE, s.getMinValue());
280 proto->write(MAX_VALUE, s.getMaxValue());
281 proto->write(RESOLUTION, s.getResolution());
282 proto->write(POWER_USAGE, s.getPowerUsage());
283 proto->end(token);
284 return true;
285 });
286 }
287
~SensorList()288 SensorList::~SensorList() {
289 }
290
291 } // namespace SensorServiceUtil
292 } // namespace android
293
294