• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.car.vms;
18 
19 import android.annotation.CallbackExecutor;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.car.Car;
24 import android.car.CarManagerBase;
25 import android.car.annotation.AddedInOrBefore;
26 import android.car.annotation.RequiredFeature;
27 import android.car.vms.VmsClientManager.VmsClientCallback;
28 
29 import com.android.internal.annotations.GuardedBy;
30 
31 import java.util.Objects;
32 import java.util.Set;
33 import java.util.concurrent.CountDownLatch;
34 import java.util.concurrent.Executor;
35 import java.util.concurrent.TimeUnit;
36 
37 /**
38  * API implementation for use by Vehicle Map Service subscribers.
39  *
40  * Supports a single client callback that can subscribe and unsubscribe to different data layers.
41  * {@link #setVmsSubscriberClientCallback} must be called before any subscription operations.
42  *
43  * @deprecated Use {@link VmsClientManager} instead
44  * @hide
45  */
46 @RequiredFeature(Car.VMS_SUBSCRIBER_SERVICE)
47 @Deprecated
48 @SystemApi
49 public final class VmsSubscriberManager extends CarManagerBase {
50     private static final long CLIENT_READY_TIMEOUT_MS = 500;
51     private static final byte[] DEFAULT_PUBLISHER_INFO = new byte[0];
52 
53     /**
54      * Callback interface for Vehicle Map Service subscribers.
55      */
56     public interface VmsSubscriberClientCallback {
57         /**
58          * Called when a data packet is received.
59          *
60          * @param layer   subscribed layer that packet was received for
61          * @param payload data packet that was received
62          */
63         @AddedInOrBefore(majorVersion = 33)
onVmsMessageReceived(@onNull VmsLayer layer, byte[] payload)64         void onVmsMessageReceived(@NonNull VmsLayer layer, byte[] payload);
65 
66         /**
67          * Called when set of available data layers changes.
68          *
69          * @param availableLayers set of available data layers
70          */
71         @AddedInOrBefore(majorVersion = 33)
onLayersAvailabilityChanged(@onNull VmsAvailableLayers availableLayers)72         void onLayersAvailabilityChanged(@NonNull VmsAvailableLayers availableLayers);
73     }
74 
75     private final VmsClientManager mClientManager;
76 
77     private final Object mLock = new Object();
78 
79     @GuardedBy("mLock")
80     private @Nullable VmsClient mClient;
81 
82     @GuardedBy("mLock")
83     private @Nullable VmsClientCallback mClientCallback;
84 
85     private final VmsSubscriptionHelper mSubscriptionHelper =
86             new VmsSubscriptionHelper(this::setSubscriptions);
87 
88     /**
89      * @hide
90      */
91     @AddedInOrBefore(majorVersion = 33)
wrap(Car car, @Nullable VmsClientManager clientManager)92     public static VmsSubscriberManager wrap(Car car, @Nullable VmsClientManager clientManager) {
93         if (clientManager == null) {
94             return null;
95         }
96         return new VmsSubscriberManager(car, clientManager);
97     }
98 
VmsSubscriberManager(Car car, VmsClientManager clientManager)99     private VmsSubscriberManager(Car car, VmsClientManager clientManager) {
100         super(car);
101         mClientManager = clientManager;
102     }
103 
104     /**
105      * Sets the subscriber client's callback, for receiving layer availability and data events.
106      *
107      * @param executor       {@link Executor} to handle the callbacks
108      * @param clientCallback subscriber callback that will handle events
109      * @throws IllegalStateException if the client callback was already set
110      */
111     @AddedInOrBefore(majorVersion = 33)
setVmsSubscriberClientCallback( @onNull @allbackExecutor Executor executor, @NonNull VmsSubscriberClientCallback clientCallback)112     public void setVmsSubscriberClientCallback(
113             @NonNull @CallbackExecutor Executor executor,
114             @NonNull VmsSubscriberClientCallback clientCallback) {
115         Objects.requireNonNull(clientCallback, "clientCallback cannot be null");
116         Objects.requireNonNull(executor, "executor cannot be null");
117         CountDownLatch clientReady;
118         synchronized (mLock) {
119             if (mClientCallback != null) {
120                 throw new IllegalStateException("Client callback is already configured.");
121             }
122             clientReady = new CountDownLatch(1);
123             mClientCallback = new SubscriberCallbackWrapper(clientCallback, clientReady);
124             // Register callback with broker service
125             mClientManager.registerVmsClientCallback(executor, mClientCallback,
126                     /* legacyClient= */ true);
127         }
128 
129         try {
130             // Wait for VmsClient to be available
131             if (!clientReady.await(CLIENT_READY_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
132                 clearVmsSubscriberClientCallback();
133                 throw new IllegalStateException("Subscriber client is not ready");
134             }
135         } catch (InterruptedException e) {
136             clearVmsSubscriberClientCallback();
137             Thread.currentThread().interrupt();
138             throw new IllegalStateException("Interrupted while waiting for subscriber client", e);
139         }
140     }
141 
142     /**
143      * Clears the subscriber client's callback.
144      */
145     @AddedInOrBefore(majorVersion = 33)
clearVmsSubscriberClientCallback()146     public void clearVmsSubscriberClientCallback() {
147         synchronized (mLock) {
148             mClientManager.unregisterVmsClientCallback(mClientCallback);
149             mClient = null;
150             mClientCallback = null;
151         }
152     }
153 
154     /**
155      * Gets a publisher's self-reported description information.
156      *
157      * @param publisherId publisher ID to retrieve information for
158      * @return serialized publisher information, in a vendor-specific format
159      */
160     @NonNull
161     @AddedInOrBefore(majorVersion = 33)
getPublisherInfo(int publisherId)162     public byte[] getPublisherInfo(int publisherId) {
163         byte[] publisherInfo = getVmsClient().getProviderDescription(publisherId);
164         return publisherInfo != null ? publisherInfo : DEFAULT_PUBLISHER_INFO;
165     }
166 
167     /**
168      * Gets all layers available for subscription.
169      *
170      * @return available layers
171      */
172     @NonNull
173     @AddedInOrBefore(majorVersion = 33)
getAvailableLayers()174     public VmsAvailableLayers getAvailableLayers() {
175         return getVmsClient().getAvailableLayers();
176     }
177 
178     /**
179      * Subscribes to data packets for a specific layer.
180      *
181      * @param layer layer to subscribe to
182      * @throws IllegalStateException if the client callback was not set via
183      *                               {@link #setVmsSubscriberClientCallback}.
184      */
185     @AddedInOrBefore(majorVersion = 33)
subscribe(@onNull VmsLayer layer)186     public void subscribe(@NonNull VmsLayer layer) {
187         mSubscriptionHelper.subscribe(layer);
188     }
189 
190     /**
191      * Subscribes to data packets for a specific layer from a specific publisher.
192      *
193      * @param layer       layer to subscribe to
194      * @param publisherId a publisher of the layer
195      * @throws IllegalStateException if the client callback was not set via
196      *                               {@link #setVmsSubscriberClientCallback}.
197      */
198     @AddedInOrBefore(majorVersion = 33)
subscribe(@onNull VmsLayer layer, int publisherId)199     public void subscribe(@NonNull VmsLayer layer, int publisherId) {
200         mSubscriptionHelper.subscribe(layer, publisherId);
201     }
202 
203     /**
204      * Start monitoring all messages for all layers, regardless of subscriptions.
205      */
206     @AddedInOrBefore(majorVersion = 33)
startMonitoring()207     public void startMonitoring() {
208         getVmsClient().setMonitoringEnabled(true);
209     }
210 
211     /**
212      * Unsubscribes from data packets for a specific layer.
213      *
214      * @param layer layer to unsubscribe from
215      * @throws IllegalStateException if the client callback was not set via
216      *                               {@link #setVmsSubscriberClientCallback}.
217      */
218     @AddedInOrBefore(majorVersion = 33)
unsubscribe(@onNull VmsLayer layer)219     public void unsubscribe(@NonNull VmsLayer layer) {
220         mSubscriptionHelper.unsubscribe(layer);
221     }
222 
223     /**
224      * Unsubscribes from data packets for a specific layer from a specific publisher.
225      *
226      * @param layer       layer to unsubscribe from
227      * @param publisherId a publisher of the layer
228      * @throws IllegalStateException if the client callback was not set via
229      *                               {@link #setVmsSubscriberClientCallback}.
230      */
231     @AddedInOrBefore(majorVersion = 33)
unsubscribe(@onNull VmsLayer layer, int publisherId)232     public void unsubscribe(@NonNull VmsLayer layer, int publisherId) {
233         mSubscriptionHelper.unsubscribe(layer, publisherId);
234     }
235 
236     /**
237      * Stop monitoring. Only receive messages for layers which have been subscribed to."
238      */
239     @AddedInOrBefore(majorVersion = 33)
stopMonitoring()240     public void stopMonitoring() {
241         getVmsClient().setMonitoringEnabled(false);
242     }
243 
244     /**
245      * @hide
246      */
247     @Override
248     @AddedInOrBefore(majorVersion = 33)
onCarDisconnected()249     public void onCarDisconnected() {}
250 
setSubscriptions(Set<VmsAssociatedLayer> subscriptions)251     private void setSubscriptions(Set<VmsAssociatedLayer> subscriptions) {
252         getVmsClient().setSubscriptions(subscriptions);
253     }
254 
getVmsClient()255     private VmsClient getVmsClient() {
256         synchronized (mLock) {
257             if (mClient == null) {
258                 throw new IllegalStateException("VMS client connection is not ready");
259             }
260             return mClient;
261         }
262     }
263 
264     private final class SubscriberCallbackWrapper implements VmsClientCallback {
265         private final VmsSubscriberClientCallback mCallback;
266         private final CountDownLatch mClientReady;
267 
SubscriberCallbackWrapper(VmsSubscriberClientCallback callback, CountDownLatch clientReady)268         SubscriberCallbackWrapper(VmsSubscriberClientCallback callback,
269                 CountDownLatch clientReady) {
270             mCallback = callback;
271             mClientReady = clientReady;
272         }
273 
274         @Override
onClientConnected(VmsClient client)275         public void onClientConnected(VmsClient client) {
276             synchronized (mLock) {
277                 mClient = client;
278             }
279             mClientReady.countDown();
280         }
281 
282         @Override
onSubscriptionStateChanged(VmsSubscriptionState subscriptionState)283         public void onSubscriptionStateChanged(VmsSubscriptionState subscriptionState) {
284             // Ignored
285         }
286 
287         @Override
onLayerAvailabilityChanged(VmsAvailableLayers availableLayers)288         public void onLayerAvailabilityChanged(VmsAvailableLayers availableLayers) {
289             mCallback.onLayersAvailabilityChanged(availableLayers);
290         }
291 
292         @Override
onPacketReceived(int providerId, VmsLayer layer, byte[] packet)293         public void onPacketReceived(int providerId, VmsLayer layer, byte[] packet) {
294             mCallback.onVmsMessageReceived(layer, packet);
295         }
296     }
297 }
298