1 /*
2  * Copyright (C) 2017 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;
18 
19 import android.car.hardware.CarSensorManager;
20 import android.os.IBinder;
21 
22 import java.util.LinkedList;
23 
24 /**
25  * This class wraps a set of listeners of a given type of event, grouped by event-transmission rate.
26  * This is logic that is common to different services that need to receive and rebroadcast events.
27  * @param <ClientType> The type of event listener.
28  */
29 public class Listeners<ClientType extends com.android.car.Listeners.IListener> {
30     public interface IListener extends IBinder.DeathRecipient {
release()31         void release();
32     }
33 
34     public static class ClientWithRate<ClientType extends IListener> {
35         private final ClientType mClient;
36         /** rate requested from client */
37         private int mRate;
38 
ClientWithRate(ClientType client, int rate)39         ClientWithRate(ClientType client, int rate) {
40             mClient = client;
41             mRate = rate;
42         }
43 
44         @Override
equals(Object o)45         public boolean equals(Object o) {
46             //TODO(egranata): is this truly necessary?
47             if (o instanceof ClientWithRate &&
48                 mClient == ((ClientWithRate) o).mClient) {
49                 return true;
50             }
51             return false;
52         }
53 
54         @Override
hashCode()55         public int hashCode() {
56             return mClient.hashCode();
57         }
58 
getRate()59         int getRate() {
60             return mRate;
61         }
62 
setRate(int rate)63         void setRate(int rate) {
64             mRate = rate;
65         }
66 
getClient()67         ClientType getClient() {
68             return mClient;
69         }
70     }
71 
72     private final LinkedList<ClientWithRate<ClientType>> mClients = new LinkedList<>();
73     /** rate sent to car */
74     private int mRate;
75 
Listeners(int rate)76     Listeners(int rate) {
77         mRate = rate;
78     }
79 
getRate()80     int getRate() {
81         return mRate;
82     }
83 
setRate(int rate)84     void setRate(int rate) {
85         mRate = rate;
86     }
87 
88     /** update rate from existing clients and return true if rate is changed. */
updateRate()89     boolean updateRate() {
90         //TODO(egranata): we might need to support other rate ranges
91         int fastestRate = CarSensorManager.SENSOR_RATE_NORMAL;
92         for (ClientWithRate<ClientType> clientWithRate: mClients) {
93             int clientRate = clientWithRate.getRate();
94             if (clientRate < fastestRate) {
95                 fastestRate = clientRate;
96             }
97         }
98         if (mRate != fastestRate) {
99             mRate = fastestRate;
100             return true;
101         }
102         return false;
103     }
104 
addClientWithRate(ClientWithRate<ClientType> clientWithRate)105     void addClientWithRate(ClientWithRate<ClientType> clientWithRate) {
106         mClients.add(clientWithRate);
107     }
108 
removeClientWithRate(ClientWithRate<ClientType> clientWithRate)109     void removeClientWithRate(ClientWithRate<ClientType> clientWithRate) {
110         mClients.remove(clientWithRate);
111     }
112 
getNumberOfClients()113     int getNumberOfClients() {
114         return mClients.size();
115     }
116 
getClients()117     Iterable<ClientWithRate<ClientType>> getClients() {
118         return mClients;
119     }
120 
findClientWithRate(ClientType client)121     ClientWithRate<ClientType> findClientWithRate(ClientType client) {
122         for (ClientWithRate<ClientType> clientWithRate: mClients) {
123             if (clientWithRate.getClient() == client) {
124                 return clientWithRate;
125             }
126         }
127         return null;
128     }
129 
release()130     void release() {
131         for (ClientWithRate<ClientType> clientWithRate: mClients) {
132             clientWithRate.getClient().release();
133         }
134         mClients.clear();
135     }
136 }
137