• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android/util/ProtoOutputStream.h>
20 #include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
21 #include <hardware/sensors.h>
22 
23 #define UNUSED(x) (void)(x)
24 
25 namespace android {
26 
27 using util::ProtoOutputStream;
28 
SensorDirectConnection(const sp<SensorService> & service,uid_t uid,const sensors_direct_mem_t * mem,int32_t halChannelHandle,const String16 & opPackageName)29 SensorService::SensorDirectConnection::SensorDirectConnection(const sp<SensorService>& service,
30         uid_t uid, const sensors_direct_mem_t *mem, int32_t halChannelHandle,
31         const String16& opPackageName)
32         : mService(service), mUid(uid), mMem(*mem),
33         mHalChannelHandle(halChannelHandle),
34         mOpPackageName(opPackageName), mDestroyed(false) {
35     mIsRateCappedBasedOnPermission = mService->isRateCappedBasedOnPermission(mOpPackageName);
36     mUserId = multiuser_get_user_id(mUid);
37     ALOGD_IF(DEBUG_CONNECTIONS, "Created SensorDirectConnection");
38 }
39 
~SensorDirectConnection()40 SensorService::SensorDirectConnection::~SensorDirectConnection() {
41     ALOGD_IF(DEBUG_CONNECTIONS, "~SensorDirectConnection %p", this);
42     destroy();
43 }
44 
destroy()45 void SensorService::SensorDirectConnection::destroy() {
46     Mutex::Autolock _l(mDestroyLock);
47     // destroy once only
48     if (mDestroyed) {
49         return;
50     }
51 
52     stopAll();
53     mService->cleanupConnection(this);
54     if (mMem.handle != nullptr) {
55         native_handle_close(mMem.handle);
56         native_handle_delete(const_cast<struct native_handle*>(mMem.handle));
57     }
58     mDestroyed = true;
59 }
60 
onFirstRef()61 void SensorService::SensorDirectConnection::onFirstRef() {
62 }
63 
dump(String8 & result) const64 void SensorService::SensorDirectConnection::dump(String8& result) const {
65     Mutex::Autolock _l(mConnectionLock);
66     result.appendFormat("\tPackage %s, HAL channel handle %d, total sensor activated %zu\n",
67             String8(mOpPackageName).string(), getHalChannelHandle(), mActivated.size());
68     for (auto &i : mActivated) {
69         result.appendFormat("\t\tSensor %#08x, rate %d\n", i.first, i.second);
70     }
71 }
72 
73 /**
74  * Dump debugging information as android.service.SensorDirectConnectionProto protobuf message using
75  * ProtoOutputStream.
76  *
77  * See proto definition and some notes about ProtoOutputStream in
78  * frameworks/base/core/proto/android/service/sensor_service.proto
79  */
dump(ProtoOutputStream * proto) const80 void SensorService::SensorDirectConnection::dump(ProtoOutputStream* proto) const {
81     using namespace service::SensorDirectConnectionProto;
82     Mutex::Autolock _l(mConnectionLock);
83     proto->write(PACKAGE_NAME, std::string(String8(mOpPackageName).string()));
84     proto->write(HAL_CHANNEL_HANDLE, getHalChannelHandle());
85     proto->write(NUM_SENSOR_ACTIVATED, int(mActivated.size()));
86     for (auto &i : mActivated) {
87         uint64_t token = proto->start(SENSORS);
88         proto->write(SensorProto::SENSOR, i.first);
89         proto->write(SensorProto::RATE, i.second);
90         proto->end(token);
91     }
92 }
93 
getSensorChannel() const94 sp<BitTube> SensorService::SensorDirectConnection::getSensorChannel() const {
95     return nullptr;
96 }
97 
onSensorAccessChanged(bool hasAccess)98 void SensorService::SensorDirectConnection::onSensorAccessChanged(bool hasAccess) {
99     if (!hasAccess) {
100         stopAll(true /* backupRecord */);
101     } else {
102         recoverAll();
103     }
104 }
105 
onMicSensorAccessChanged(bool isMicToggleOn)106 void SensorService::SensorDirectConnection::onMicSensorAccessChanged(bool isMicToggleOn) {
107     if (isMicToggleOn) {
108         capRates();
109     } else {
110         uncapRates();
111     }
112 }
113 
hasSensorAccess() const114 bool SensorService::SensorDirectConnection::hasSensorAccess() const {
115     return mService->hasSensorAccess(mUid, mOpPackageName);
116 }
117 
enableDisable(int handle,bool enabled,nsecs_t samplingPeriodNs,nsecs_t maxBatchReportLatencyNs,int reservedFlags)118 status_t SensorService::SensorDirectConnection::enableDisable(
119         int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
120         int reservedFlags) {
121     // SensorDirectConnection does not support enableDisable, parameters not used
122     UNUSED(handle);
123     UNUSED(enabled);
124     UNUSED(samplingPeriodNs);
125     UNUSED(maxBatchReportLatencyNs);
126     UNUSED(reservedFlags);
127     return INVALID_OPERATION;
128 }
129 
setEventRate(int handle,nsecs_t samplingPeriodNs)130 status_t SensorService::SensorDirectConnection::setEventRate(
131         int handle, nsecs_t samplingPeriodNs) {
132     // SensorDirectConnection does not support setEventRate, parameters not used
133     UNUSED(handle);
134     UNUSED(samplingPeriodNs);
135     return INVALID_OPERATION;
136 }
137 
flush()138 status_t SensorService::SensorDirectConnection::flush() {
139     // SensorDirectConnection does not support flush
140     return INVALID_OPERATION;
141 }
142 
configureChannel(int handle,int rateLevel)143 int32_t SensorService::SensorDirectConnection::configureChannel(int handle, int rateLevel) {
144 
145     if (handle == -1 && rateLevel == SENSOR_DIRECT_RATE_STOP) {
146         stopAll();
147         mMicRateBackup.clear();
148         return NO_ERROR;
149     }
150 
151     if (!hasSensorAccess()) {
152         return PERMISSION_DENIED;
153     }
154 
155     sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
156     if (si == nullptr) {
157         return NAME_NOT_FOUND;
158     }
159 
160     const Sensor& s = si->getSensor();
161     if (!SensorService::canAccessSensor(s, "config direct channel", mOpPackageName)) {
162         return PERMISSION_DENIED;
163     }
164 
165     if (s.getHighestDirectReportRateLevel() == 0
166             || rateLevel > s.getHighestDirectReportRateLevel()
167             || !s.isDirectChannelTypeSupported(mMem.type)) {
168         return INVALID_OPERATION;
169     }
170 
171     int requestedRateLevel = rateLevel;
172     if (mService->isSensorInCappedSet(s.getType()) && rateLevel != SENSOR_DIRECT_RATE_STOP) {
173         status_t err = mService->adjustRateLevelBasedOnMicAndPermission(&rateLevel, mOpPackageName);
174         if (err != OK) {
175             return err;
176         }
177     }
178 
179     struct sensors_direct_cfg_t config = {
180         .rate_level = rateLevel
181     };
182 
183     Mutex::Autolock _l(mConnectionLock);
184     SensorDevice& dev(SensorDevice::getInstance());
185     int ret = dev.configureDirectChannel(handle, getHalChannelHandle(), &config);
186 
187     if (rateLevel == SENSOR_DIRECT_RATE_STOP) {
188         if (ret == NO_ERROR) {
189             mActivated.erase(handle);
190             mMicRateBackup.erase(handle);
191         } else if (ret > 0) {
192             ret = UNKNOWN_ERROR;
193         }
194     } else {
195         if (ret > 0) {
196             mActivated[handle] = rateLevel;
197             if (mService->isSensorInCappedSet(s.getType())) {
198                 // Back up the rates that the app is allowed to have if the mic toggle is off
199                 // This is used in the uncapRates() function.
200                 if (!mIsRateCappedBasedOnPermission ||
201                             requestedRateLevel <= SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL) {
202                     mMicRateBackup[handle] = requestedRateLevel;
203                 } else {
204                     mMicRateBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
205                 }
206             }
207         }
208     }
209 
210     return ret;
211 }
212 
capRates()213 void SensorService::SensorDirectConnection::capRates() {
214     Mutex::Autolock _l(mConnectionLock);
215     const struct sensors_direct_cfg_t capConfig = {
216         .rate_level = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL
217     };
218 
219     const struct sensors_direct_cfg_t stopConfig = {
220         .rate_level = SENSOR_DIRECT_RATE_STOP
221     };
222 
223     // If our requests are in the backup, then we shouldn't activate sensors from here
224     bool temporarilyStopped = mActivated.empty() && !mActivatedBackup.empty();
225     std::unordered_map<int, int>& existingConnections =
226                     (!temporarilyStopped) ? mActivated : mActivatedBackup;
227 
228     SensorDevice& dev(SensorDevice::getInstance());
229     for (auto &i : existingConnections) {
230         int handle = i.first;
231         int rateLevel = i.second;
232         sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
233         if (si != nullptr) {
234             const Sensor& s = si->getSensor();
235             if (mService->isSensorInCappedSet(s.getType()) &&
236                         rateLevel > SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL) {
237                 mMicRateBackup[handle] = rateLevel;
238                 // Modify the rate kept by the existing map
239                 existingConnections[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
240                 // Only reconfigure the channel if it's ongoing
241                 if (!temporarilyStopped) {
242                     // Stopping before reconfiguring is the well-tested path in CTS
243                     dev.configureDirectChannel(handle, getHalChannelHandle(), &stopConfig);
244                     dev.configureDirectChannel(handle, getHalChannelHandle(), &capConfig);
245                 }
246             }
247         }
248     }
249 }
250 
uncapRates()251 void SensorService::SensorDirectConnection::uncapRates() {
252     Mutex::Autolock _l(mConnectionLock);
253 
254     // If our requests are in the backup, then we shouldn't activate sensors from here
255     bool temporarilyStopped = mActivated.empty() && !mActivatedBackup.empty();
256     std::unordered_map<int, int>& existingConnections =
257                     (!temporarilyStopped) ? mActivated : mActivatedBackup;
258 
259     const struct sensors_direct_cfg_t stopConfig = {
260         .rate_level = SENSOR_DIRECT_RATE_STOP
261     };
262     SensorDevice& dev(SensorDevice::getInstance());
263     for (auto &i : mMicRateBackup) {
264         int handle = i.first;
265         int rateLevel = i.second;
266 
267         const struct sensors_direct_cfg_t config = {
268             .rate_level = rateLevel
269         };
270 
271         // Modify the rate kept by the existing map
272         existingConnections[handle] = rateLevel;
273 
274         // Only reconfigure the channel if it's ongoing
275         if (!temporarilyStopped) {
276             // Stopping before reconfiguring is the well-tested path in CTS
277             dev.configureDirectChannel(handle, getHalChannelHandle(), &stopConfig);
278             dev.configureDirectChannel(handle, getHalChannelHandle(), &config);
279         }
280     }
281     mMicRateBackup.clear();
282 }
283 
stopAll(bool backupRecord)284 void SensorService::SensorDirectConnection::stopAll(bool backupRecord) {
285     Mutex::Autolock _l(mConnectionLock);
286     stopAllLocked(backupRecord);
287 }
288 
stopAllLocked(bool backupRecord)289 void SensorService::SensorDirectConnection::stopAllLocked(bool backupRecord) {
290     struct sensors_direct_cfg_t config = {
291         .rate_level = SENSOR_DIRECT_RATE_STOP
292     };
293 
294     SensorDevice& dev(SensorDevice::getInstance());
295     for (auto &i : mActivated) {
296         dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
297     }
298 
299     if (backupRecord && mActivatedBackup.empty()) {
300         mActivatedBackup = mActivated;
301     }
302     mActivated.clear();
303 }
304 
recoverAll()305 void SensorService::SensorDirectConnection::recoverAll() {
306     Mutex::Autolock _l(mConnectionLock);
307     if (!mActivatedBackup.empty()) {
308         stopAllLocked(false);
309 
310         SensorDevice& dev(SensorDevice::getInstance());
311 
312         // recover list of report from backup
313         ALOG_ASSERT(mActivated.empty(),
314                     "mActivated must be empty if mActivatedBackup was non-empty");
315         mActivated = mActivatedBackup;
316         mActivatedBackup.clear();
317 
318         // re-enable them
319         for (auto &i : mActivated) {
320             struct sensors_direct_cfg_t config = {
321                 .rate_level = i.second
322             };
323             dev.configureDirectChannel(i.first, getHalChannelHandle(), &config);
324         }
325     }
326 }
327 
getHalChannelHandle() const328 int32_t SensorService::SensorDirectConnection::getHalChannelHandle() const {
329     return mHalChannelHandle;
330 }
331 
isEquivalent(const sensors_direct_mem_t * mem) const332 bool SensorService::SensorDirectConnection::isEquivalent(const sensors_direct_mem_t *mem) const {
333     bool ret = false;
334 
335     if (mMem.type == mem->type) {
336         switch (mMem.type) {
337             case SENSOR_DIRECT_MEM_TYPE_ASHMEM: {
338                 // there is no known method to test if two ashmem fds are equivalent besides
339                 // trivially comparing the fd values (ino number from fstat() are always the
340                 // same, pointing to "/dev/ashmem").
341                 int fd1 = mMem.handle->data[0];
342                 int fd2 = mem->handle->data[0];
343                 ret = (fd1 == fd2);
344                 break;
345             }
346             case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
347                 // there is no known method to test if two gralloc handle are equivalent
348                 ret = false;
349                 break;
350             default:
351                 // should never happen
352                 ALOGE("Unexpected mem type %d", mMem.type);
353                 ret = true;
354                 break;
355         }
356     }
357     return ret;
358 }
359 
360 } // namespace android
361 
362