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