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 <algorithm>
18 
19 #include "chre/core/sensor_request.h"
20 #include "chre/platform/assert.h"
21 #include "chre/platform/fatal_error.h"
22 
23 namespace chre {
24 namespace {
25 
getBatchInterval(const SensorRequest & request)26 Nanoseconds getBatchInterval(const SensorRequest &request) {
27   // With capping in SensorRequest constructor, interval + latency < UINT64_MAX.
28   // When the return value is default, request latency (instead of batch
29   // interval) will be used to compute the merged latency.
30   if (request.getInterval() == Nanoseconds(CHRE_SENSOR_INTERVAL_DEFAULT) ||
31       request.getLatency() == Nanoseconds(CHRE_SENSOR_LATENCY_DEFAULT)) {
32     return Nanoseconds(CHRE_SENSOR_BATCH_INTERVAL_DEFAULT);
33   } else {
34     return request.getInterval() + request.getLatency();
35   }
36 }
37 
38 }  // namespace
39 
SensorRequest()40 SensorRequest::SensorRequest()
41     : SensorRequest(SensorMode::Off, Nanoseconds(CHRE_SENSOR_INTERVAL_DEFAULT),
42                     Nanoseconds(CHRE_SENSOR_LATENCY_DEFAULT)) {}
43 
SensorRequest(SensorMode mode,Nanoseconds interval,Nanoseconds latency)44 SensorRequest::SensorRequest(SensorMode mode, Nanoseconds interval,
45                              Nanoseconds latency)
46     : SensorRequest(kInvalidInstanceId, mode, interval, latency) {}
47 
SensorRequest(uint32_t instanceId,SensorMode mode,Nanoseconds interval,Nanoseconds latency)48 SensorRequest::SensorRequest(uint32_t instanceId, SensorMode mode,
49                              Nanoseconds interval, Nanoseconds latency)
50     : mInterval(interval),
51       mLatency(latency),
52       mInstanceId(instanceId),
53       mMode(mode) {
54   // cap non-default interval/latency to ensure no overflow in CHRE internal
55   // operations.
56   if (interval != Nanoseconds(CHRE_SENSOR_INTERVAL_DEFAULT)) {
57     mInterval = std::min(interval, Nanoseconds(kMaxIntervalLatencyNs));
58   }
59   if (latency != Nanoseconds(CHRE_SENSOR_LATENCY_DEFAULT)) {
60     mLatency = std::min(latency, Nanoseconds(kMaxIntervalLatencyNs));
61   }
62 }
63 
isEquivalentTo(const SensorRequest & request) const64 bool SensorRequest::isEquivalentTo(const SensorRequest &request) const {
65   return (mMode == request.mMode && mInterval == request.mInterval &&
66           mLatency == request.mLatency &&
67           mBiasUpdatesRequested == request.mBiasUpdatesRequested);
68 }
69 
onlyBiasRequestUpdated(const SensorRequest & request) const70 bool SensorRequest::onlyBiasRequestUpdated(const SensorRequest &request) const {
71   return (mMode == request.mMode && mInterval == request.mInterval &&
72           mLatency == request.mLatency &&
73           mBiasUpdatesRequested != request.mBiasUpdatesRequested);
74 }
75 
mergeWith(const SensorRequest & request)76 bool SensorRequest::mergeWith(const SensorRequest &request) {
77   bool attributesChanged = false;
78   if (request.mMode != SensorMode::Off) {
79     // Calculate minimum batch interval before mInterval is modified.
80     Nanoseconds batchInterval =
81         std::min(getBatchInterval(*this), getBatchInterval(request));
82 
83     if (request.mInterval < mInterval) {
84       mInterval = request.mInterval;
85       attributesChanged = true;
86     }
87 
88     if (batchInterval == Nanoseconds(CHRE_SENSOR_BATCH_INTERVAL_DEFAULT)) {
89       // If batchInterval is default, it can't be effectively calculated.
90       // Use request.mLatency for more aggressive latency merging in this case.
91       Nanoseconds latency = request.mLatency;
92       if (latency < mLatency) {
93         mLatency = latency;
94         attributesChanged = true;
95       }
96     } else {
97       Nanoseconds latency = (batchInterval - mInterval);
98 
99       // Note that while batchInterval can only shrink after merging, latency
100       // can grow if the merged interval is lower.
101       // Also, it's guaranteed that latency <= kMaxIntervalLatencyNs.
102       if (latency != mLatency) {
103         mLatency = latency;
104         attributesChanged = true;
105       }
106     }
107 
108     // Compute the highest priority mode. Active continuous is the highest
109     // priority and passive one-shot is the lowest.
110     SensorMode maximalSensorMode = SensorMode::Off;
111     if (mMode == SensorMode::ActiveContinuous ||
112         request.mMode == SensorMode::ActiveContinuous) {
113       maximalSensorMode = SensorMode::ActiveContinuous;
114     } else if (mMode == SensorMode::ActiveOneShot ||
115                request.mMode == SensorMode::ActiveOneShot) {
116       maximalSensorMode = SensorMode::ActiveOneShot;
117     } else if (mMode == SensorMode::PassiveContinuous ||
118                request.mMode == SensorMode::PassiveContinuous) {
119       maximalSensorMode = SensorMode::PassiveContinuous;
120     } else if (mMode == SensorMode::PassiveOneShot ||
121                request.mMode == SensorMode::PassiveOneShot) {
122       maximalSensorMode = SensorMode::PassiveOneShot;
123     } else {
124       CHRE_ASSERT(false);
125     }
126 
127     if (mMode != maximalSensorMode) {
128       mMode = maximalSensorMode;
129       attributesChanged = true;
130     }
131 
132     if (!mBiasUpdatesRequested && request.mBiasUpdatesRequested) {
133       mBiasUpdatesRequested = true;
134       attributesChanged = true;
135     }
136   }
137 
138   return attributesChanged;
139 }
140 
141 }  // namespace chre
142