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(uint16_t instanceId,SensorMode mode,Nanoseconds interval,Nanoseconds latency)48 SensorRequest::SensorRequest(uint16_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