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             return (o instanceof ClientWithRate) && mClient == ((ClientWithRate) o).mClient;
48         }
49 
50         @Override
hashCode()51         public int hashCode() {
52             return mClient.hashCode();
53         }
54 
getRate()55         int getRate() {
56             return mRate;
57         }
58 
setRate(int rate)59         void setRate(int rate) {
60             mRate = rate;
61         }
62 
getClient()63         ClientType getClient() {
64             return mClient;
65         }
66     }
67 
68     private final LinkedList<ClientWithRate<ClientType>> mClients = new LinkedList<>();
69     /** rate sent to car */
70     private int mRate;
71 
Listeners(int rate)72     Listeners(int rate) {
73         mRate = rate;
74     }
75 
getRate()76     int getRate() {
77         return mRate;
78     }
79 
setRate(int rate)80     void setRate(int rate) {
81         mRate = rate;
82     }
83 
84     /** update rate from existing clients and return true if rate is changed. */
updateRate()85     boolean updateRate() {
86         //TODO(egranata): we might need to support other rate ranges
87         int fastestRate = CarSensorManager.SENSOR_RATE_NORMAL;
88         for (ClientWithRate<ClientType> clientWithRate: mClients) {
89             int clientRate = clientWithRate.getRate();
90             if (clientRate < fastestRate) {
91                 fastestRate = clientRate;
92             }
93         }
94         if (mRate != fastestRate) {
95             mRate = fastestRate;
96             return true;
97         }
98         return false;
99     }
100 
addClientWithRate(ClientWithRate<ClientType> clientWithRate)101     void addClientWithRate(ClientWithRate<ClientType> clientWithRate) {
102         mClients.add(clientWithRate);
103     }
104 
removeClientWithRate(ClientWithRate<ClientType> clientWithRate)105     void removeClientWithRate(ClientWithRate<ClientType> clientWithRate) {
106         mClients.remove(clientWithRate);
107     }
108 
getNumberOfClients()109     int getNumberOfClients() {
110         return mClients.size();
111     }
112 
getClients()113     Iterable<ClientWithRate<ClientType>> getClients() {
114         return mClients;
115     }
116 
findClientWithRate(ClientType client)117     ClientWithRate<ClientType> findClientWithRate(ClientType client) {
118         for (ClientWithRate<ClientType> clientWithRate: mClients) {
119             if (clientWithRate.getClient() == client) {
120                 return clientWithRate;
121             }
122         }
123         return null;
124     }
125 
release()126     void release() {
127         for (ClientWithRate<ClientType> clientWithRate: mClients) {
128             clientWithRate.getClient().release();
129         }
130         mClients.clear();
131     }
132 }
133