1 /* 2 * Copyright (C) 2018 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 package com.android.car.internal; 18 19 import android.util.SparseArray; 20 21 import java.util.Collection; 22 import java.util.Collections; 23 import java.util.HashMap; 24 import java.util.Map; 25 26 /** 27 * Represent listeners for a property grouped by their rate. 28 * T is a type of EventListener such as CarPropertyEventCallback 29 * in {@link android.car.hardware.property.CarPropertyManager} 30 * @param <T> 31 * @hide 32 */ 33 public class CarRatedFloatListeners<T> { 34 private static final float NANOSECOND_PER_SECOND = 1000 * 1000 * 1000; 35 private final Map<T, Float> mListenersToRate = new HashMap<>(4); 36 37 private final Map<T, Long> mListenersUpdateTime = new HashMap<>(4); 38 39 private float mUpdateRate; 40 41 // key: areaId, value: lastUpdateTime in nanosecond 42 protected SparseArray<Long> mAreaIdToLastUpdateTime = new SparseArray<>(); 43 CarRatedFloatListeners(float rate)44 protected CarRatedFloatListeners(float rate) { 45 mUpdateRate = rate; 46 } 47 48 /** Check listener */ contains(T listener)49 public boolean contains(T listener) { 50 return mListenersToRate.containsKey(listener); 51 } 52 /** Return current rate after updating */ getRate()53 public float getRate() { 54 return mUpdateRate; 55 } 56 57 /** 58 * Remove given listener from the list and update rate if necessary. 59 * 60 * @param listener 61 * @return true if rate was updated. Otherwise, returns false. 62 */ remove(T listener)63 public boolean remove(T listener) { 64 mListenersToRate.remove(listener); 65 mListenersUpdateTime.remove(listener); 66 if (mListenersToRate.isEmpty()) { 67 return false; 68 } 69 Float updateRate = Collections.max(mListenersToRate.values()); 70 if (updateRate != mUpdateRate) { 71 mUpdateRate = updateRate; 72 return true; 73 } 74 return false; 75 } 76 isEmpty()77 public boolean isEmpty() { 78 return mListenersToRate.isEmpty(); 79 } 80 81 /** 82 * Add given listener to the list and update rate if necessary. 83 * 84 * @param listener if null, add part is skipped. 85 * @param updateRate 86 * @return true if rate was updated. Otherwise, returns false. 87 */ addAndUpdateRate(T listener, float updateRate)88 public boolean addAndUpdateRate(T listener, float updateRate) { 89 Float oldUpdateRate = mListenersToRate.put(listener, updateRate); 90 mListenersUpdateTime.put(listener, 0L); 91 if (mUpdateRate < updateRate) { 92 mUpdateRate = updateRate; 93 return true; 94 } else if (oldUpdateRate != null && oldUpdateRate == mUpdateRate) { 95 Float newUpdateRate = Collections.max(mListenersToRate.values()); 96 if (newUpdateRate != mUpdateRate) { 97 mUpdateRate = newUpdateRate; 98 return true; 99 } 100 } 101 return false; 102 } 103 104 /** 105 * Check whether listener should be notified by events. 106 * 107 * @param listener 108 * @param eventTimeStamp 109 * @return true if listener need to be notified. 110 */ needUpdateForSelectedListener(T listener, long eventTimeStamp)111 public boolean needUpdateForSelectedListener(T listener, long eventTimeStamp) { 112 Long nextUpdateTime = mListenersUpdateTime.get(listener); 113 Float updateRate = mListenersToRate.get(listener); 114 /** Update ON_CHANGE property. */ 115 if (updateRate == 0) { 116 return true; 117 } 118 if (nextUpdateTime <= eventTimeStamp) { 119 Float cycle = NANOSECOND_PER_SECOND / updateRate; 120 nextUpdateTime = eventTimeStamp + cycle.longValue(); 121 mListenersUpdateTime.put(listener, nextUpdateTime); 122 return true; 123 } 124 return false; 125 } 126 127 /** 128 * @param areaId AreaId in CarPropertyValue 129 * @param eventTime TimeStamp in CarPropertyValue 130 * @return true if eventTime is greater than the last event time for the same areaId. 131 */ needUpdateForAreaId(int areaId, long eventTime)132 public boolean needUpdateForAreaId(int areaId, long eventTime) { 133 long lastUpdateTime = mAreaIdToLastUpdateTime.get(areaId, 0L); 134 if (eventTime >= lastUpdateTime) { 135 mAreaIdToLastUpdateTime.put(areaId, eventTime); 136 return true; 137 } 138 return false; 139 } 140 141 getListeners()142 public Collection<T> getListeners() { 143 return mListenersToRate.keySet(); 144 } 145 } 146 147