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