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