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 
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 
40 SensorRequest::SensorRequest()
41     : SensorRequest(SensorMode::Off,
42                     Nanoseconds(CHRE_SENSOR_INTERVAL_DEFAULT),
43                     Nanoseconds(CHRE_SENSOR_LATENCY_DEFAULT)) {}
44 
45 SensorRequest::SensorRequest(SensorMode mode, Nanoseconds interval,
46                              Nanoseconds latency)
47     : SensorRequest(nullptr /* nanoapp */, mode, interval, latency) {}
48 
49 SensorRequest::SensorRequest(Nanoapp *nanoapp, SensorMode mode,
50                              Nanoseconds interval, Nanoseconds latency)
51     : mNanoapp(nanoapp), mInterval(interval), mLatency(latency), mMode(mode) {
52   // cap non-default interval/latency to ensure no overflow in CHRE internal
53   // operations.
54   if (interval != Nanoseconds(CHRE_SENSOR_INTERVAL_DEFAULT)) {
55     mInterval = std::min(interval, Nanoseconds(kMaxIntervalLatencyNs));
56   }
57   if (latency != Nanoseconds(CHRE_SENSOR_LATENCY_DEFAULT)) {
58     mLatency = std::min(latency, Nanoseconds(kMaxIntervalLatencyNs));
59   }
60 }
61 
62 bool SensorRequest::isEquivalentTo(const SensorRequest& request) const {
63   return (mMode == request.mMode
64       && mInterval == request.mInterval
65       && mLatency == request.mLatency);
66 }
67 
68 bool SensorRequest::mergeWith(const SensorRequest& request) {
69   bool attributesChanged = false;
70   if (request.mMode != SensorMode::Off) {
71     // Calculate minimum batch interval before mInterval is modified.
72     Nanoseconds batchInterval = std::min(getBatchInterval(*this),
73                                          getBatchInterval(request));
74 
75     if (request.mInterval < mInterval) {
76       mInterval = request.mInterval;
77       attributesChanged = true;
78     }
79 
80     if (batchInterval == Nanoseconds(CHRE_SENSOR_BATCH_INTERVAL_DEFAULT)) {
81       // If batchInterval is default, it can't be effectively calculated.
82       // Use request.mLatency for more aggressive latency merging in this case.
83       Nanoseconds latency = request.mLatency;
84       if (latency < mLatency) {
85         mLatency = latency;
86         attributesChanged = true;
87       }
88     } else {
89       Nanoseconds latency = (batchInterval - mInterval);
90 
91       // Note that while batchInterval can only shrink after merging, latency
92       // can grow if the merged interval is lower.
93       // Also, it's guaranteed that latency <= kMaxIntervalLatencyNs.
94       if (latency != mLatency) {
95         mLatency = latency;
96         attributesChanged = true;
97       }
98     }
99 
100     // Compute the highest priority mode. Active continuous is the highest
101     // priority and passive one-shot is the lowest.
102     SensorMode maximalSensorMode = SensorMode::Off;
103     if (mMode == SensorMode::ActiveContinuous
104         || request.mMode == SensorMode::ActiveContinuous) {
105       maximalSensorMode = SensorMode::ActiveContinuous;
106     } else if (mMode == SensorMode::ActiveOneShot
107         || request.mMode == SensorMode::ActiveOneShot) {
108       maximalSensorMode = SensorMode::ActiveOneShot;
109     } else if (mMode == SensorMode::PassiveContinuous
110         || request.mMode == SensorMode::PassiveContinuous) {
111       maximalSensorMode = SensorMode::PassiveContinuous;
112     } else if (mMode == SensorMode::PassiveOneShot
113         || request.mMode == SensorMode::PassiveOneShot) {
114       maximalSensorMode = SensorMode::PassiveOneShot;
115     } else {
116       CHRE_ASSERT(false);
117     }
118 
119     if (mMode != maximalSensorMode) {
120       mMode = maximalSensorMode;
121       attributesChanged = true;
122     }
123   }
124 
125   return attributesChanged;
126 }
127 
128 }  // namespace chre
129