blob: 06a06ae30ae7ff8ac92fbf887981ad61758d44ab [file] [log] [blame]
Antonio Cortesa7d8ed12017-02-02 11:50:01 -08001/*
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
17package android.car.vms;
18
Anna Linetsky40f1ded2018-05-07 16:37:01 -070019import android.annotation.CallbackExecutor;
20import android.annotation.NonNull;
Asaf Rosenfeld39e4f032017-09-16 11:33:50 -070021import android.annotation.SystemApi;
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080022import android.car.CarManagerBase;
Anna Linetsky40f1ded2018-05-07 16:37:01 -070023import android.os.Binder;
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080024import android.os.IBinder;
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080025import android.os.RemoteException;
26import android.util.Log;
Demyn Plantenberg3ca12892017-06-20 21:01:34 -070027
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080028import com.android.internal.annotations.GuardedBy;
Anna Linetsky40f1ded2018-05-07 16:37:01 -070029import com.android.internal.util.Preconditions;
Demyn Plantenberg3ca12892017-06-20 21:01:34 -070030
Anna Linetsky40f1ded2018-05-07 16:37:01 -070031import java.util.concurrent.Executor;
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080032
33/**
Mark Tabry16318e22019-03-22 10:04:32 -070034 * API implementation for use by Vehicle Map Service subscribers.
35 *
36 * Supports a single client callback that can subscribe and unsubscribe to different data layers.
37 * {@link #setVmsSubscriberClientCallback} must be called before any subscription operations.
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080038 *
39 * @hide
40 */
Asaf Rosenfeld39e4f032017-09-16 11:33:50 -070041@SystemApi
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080042public final class VmsSubscriberManager implements CarManagerBase {
43 private static final boolean DBG = true;
44 private static final String TAG = "VmsSubscriberManager";
45
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080046 private final IVmsSubscriberService mVmsSubscriberService;
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -070047 private final IVmsSubscriberClient mSubscriberManagerClient;
48 private final Object mClientCallbackLock = new Object();
49 @GuardedBy("mClientCallbackLock")
50 private VmsSubscriberClientCallback mClientCallback;
Anna Linetsky40f1ded2018-05-07 16:37:01 -070051 @GuardedBy("mClientCallbackLock")
52 private Executor mExecutor;
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080053
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -070054 /**
Mark Tabry16318e22019-03-22 10:04:32 -070055 * Callback interface for Vehicle Map Service subscribers.
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -070056 */
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -070057 public interface VmsSubscriberClientCallback {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -070058 /**
Mark Tabry16318e22019-03-22 10:04:32 -070059 * Called when a data packet is received.
60 *
61 * @param layer subscribed layer that packet was received for
62 * @param payload data packet that was received
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -070063 */
Mark Tabry16318e22019-03-22 10:04:32 -070064 void onVmsMessageReceived(@NonNull VmsLayer layer, byte[] payload);
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -070065
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -070066 /**
Mark Tabry16318e22019-03-22 10:04:32 -070067 * Called when set of available data layers changes.
68 *
69 * @param availableLayers set of available data layers
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -070070 */
Mark Tabry16318e22019-03-22 10:04:32 -070071 void onLayersAvailabilityChanged(@NonNull VmsAvailableLayers availableLayers);
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080072 }
73
74 /**
Anna Linetsky40f1ded2018-05-07 16:37:01 -070075 * Hidden constructor - can only be used internally.
Mark Tabry16318e22019-03-22 10:04:32 -070076 *
Anna Linetsky40f1ded2018-05-07 16:37:01 -070077 * @hide
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080078 */
Anna Linetsky40f1ded2018-05-07 16:37:01 -070079 public VmsSubscriberManager(IBinder service) {
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080080 mVmsSubscriberService = IVmsSubscriberService.Stub.asInterface(service);
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -070081 mSubscriberManagerClient = new IVmsSubscriberClient.Stub() {
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080082 @Override
Anna Linetsky40f1ded2018-05-07 16:37:01 -070083 public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
84 Executor executor;
85 synchronized (mClientCallbackLock) {
86 executor = mExecutor;
87 }
88 if (executor == null) {
89 if (DBG) {
90 Log.d(TAG, "Executor is null in onVmsMessageReceived");
91 }
92 return;
93 }
94 Binder.clearCallingIdentity();
Mark Tabry16318e22019-03-22 10:04:32 -070095 executor.execute(() -> {
96 dispatchOnReceiveMessage(layer, payload);
97 });
Antonio Cortesa7d8ed12017-02-02 11:50:01 -080098 }
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -070099
100 @Override
Asaf Rosenfeld908811e2018-01-22 09:13:47 -0800101 public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) {
Anna Linetsky40f1ded2018-05-07 16:37:01 -0700102 Executor executor;
103 synchronized (mClientCallbackLock) {
104 executor = mExecutor;
105 }
106 if (executor == null) {
107 if (DBG) {
108 Log.d(TAG, "Executor is null in onLayersAvailabilityChanged");
109 }
110 return;
111 }
112 Binder.clearCallingIdentity();
Mark Tabry16318e22019-03-22 10:04:32 -0700113 executor.execute(() -> {
114 dispatchOnAvailabilityChangeMessage(availableLayers);
115 });
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700116 }
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800117 };
118 }
119
120 /**
Mark Tabry16318e22019-03-22 10:04:32 -0700121 * Sets the subscriber client's callback, for receiving layer availability and data events.
122 *
123 * @param executor {@link Executor} to handle the callbacks
124 * @param clientCallback subscriber callback that will handle events
125 * @throws IllegalStateException if the client callback was already set
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800126 */
Justin Pauporeccc75a32019-02-12 18:20:48 -0800127 public void setVmsSubscriberClientCallback(
128 @NonNull @CallbackExecutor Executor executor,
129 @NonNull VmsSubscriberClientCallback clientCallback) {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700130 synchronized (mClientCallbackLock) {
131 if (mClientCallback != null) {
132 throw new IllegalStateException("Client callback is already configured.");
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800133 }
Mark Tabry16318e22019-03-22 10:04:32 -0700134 mClientCallback = Preconditions.checkNotNull(clientCallback,
135 "clientCallback cannot be null");
136 mExecutor = Preconditions.checkNotNull(executor, "executor cannot be null");
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700137 }
138 try {
139 mVmsSubscriberService.addVmsSubscriberToNotifications(mSubscriberManagerClient);
140 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800141 throw e.rethrowFromSystemServer();
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700142 }
143 }
144
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700145
Anna Linetsky40f1ded2018-05-07 16:37:01 -0700146 /**
Mark Tabry16318e22019-03-22 10:04:32 -0700147 * Clears the subscriber client's callback.
Anna Linetsky40f1ded2018-05-07 16:37:01 -0700148 */
Justin Pauporeccc75a32019-02-12 18:20:48 -0800149 public void clearVmsSubscriberClientCallback() {
Anna Linetsky40f1ded2018-05-07 16:37:01 -0700150 synchronized (mClientCallbackLock) {
151 if (mExecutor == null) return;
152 }
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700153 try {
154 mVmsSubscriberService.removeVmsSubscriberToNotifications(mSubscriberManagerClient);
155 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800156 throw e.rethrowFromSystemServer();
rleix45899732018-10-18 16:36:56 +0800157 } finally {
158 synchronized (mClientCallbackLock) {
159 mClientCallback = null;
160 mExecutor = null;
161 }
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800162 }
163 }
164
165 /**
Mark Tabry16318e22019-03-22 10:04:32 -0700166 * Gets a publisher's self-reported description information.
167 *
168 * @param publisherId publisher ID to retrieve information for
169 * @return serialized publisher information, in a vendor-specific format
Asaf Rosenfeld60284892017-05-19 12:59:56 -0700170 */
Mark Tabry16318e22019-03-22 10:04:32 -0700171 @NonNull
Justin Pauporeccc75a32019-02-12 18:20:48 -0800172 public byte[] getPublisherInfo(int publisherId) {
Asaf Rosenfeld60284892017-05-19 12:59:56 -0700173 try {
174 return mVmsSubscriberService.getPublisherInfo(publisherId);
175 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800176 throw e.rethrowFromSystemServer();
Asaf Rosenfeld60284892017-05-19 12:59:56 -0700177 }
178 }
179
180 /**
Mark Tabry16318e22019-03-22 10:04:32 -0700181 * Gets all layers available for subscription.
182 *
183 * @return available layers
Asaf Rosenfeld908811e2018-01-22 09:13:47 -0800184 */
Mark Tabry16318e22019-03-22 10:04:32 -0700185 @NonNull
Justin Pauporeccc75a32019-02-12 18:20:48 -0800186 public VmsAvailableLayers getAvailableLayers() {
Asaf Rosenfeld908811e2018-01-22 09:13:47 -0800187 try {
188 return mVmsSubscriberService.getAvailableLayers();
189 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800190 throw e.rethrowFromSystemServer();
Asaf Rosenfeld908811e2018-01-22 09:13:47 -0800191 }
192 }
193
194 /**
Mark Tabry16318e22019-03-22 10:04:32 -0700195 * Subscribes to data packets for a specific layer.
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800196 *
Mark Tabry16318e22019-03-22 10:04:32 -0700197 * @param layer layer to subscribe to
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700198 * @throws IllegalStateException if the client callback was not set via
Anna Linetsky40f1ded2018-05-07 16:37:01 -0700199 * {@link #setVmsSubscriberClientCallback}.
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800200 */
Mark Tabry16318e22019-03-22 10:04:32 -0700201 public void subscribe(@NonNull VmsLayer layer) {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700202 verifySubscriptionIsAllowed();
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800203 try {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700204 mVmsSubscriberService.addVmsSubscriber(mSubscriberManagerClient, layer);
Demyn Plantenberg3ca12892017-06-20 21:01:34 -0700205 VmsOperationRecorder.get().subscribe(layer);
asafro25a87402017-02-28 16:08:17 -0800206 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800207 throw e.rethrowFromSystemServer();
asafro25a87402017-02-28 16:08:17 -0800208 }
209 }
210
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700211 /**
Mark Tabry16318e22019-03-22 10:04:32 -0700212 * Subscribes to data packets for a specific layer from a specific publisher.
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700213 *
Mark Tabry16318e22019-03-22 10:04:32 -0700214 * @param layer layer to subscribe to
215 * @param publisherId a publisher of the layer
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700216 * @throws IllegalStateException if the client callback was not set via
Anna Linetsky40f1ded2018-05-07 16:37:01 -0700217 * {@link #setVmsSubscriberClientCallback}.
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700218 */
Mark Tabry16318e22019-03-22 10:04:32 -0700219 public void subscribe(@NonNull VmsLayer layer, int publisherId) {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700220 verifySubscriptionIsAllowed();
asafro25a87402017-02-28 16:08:17 -0800221 try {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700222 mVmsSubscriberService.addVmsSubscriberToPublisher(
223 mSubscriberManagerClient, layer, publisherId);
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700224 VmsOperationRecorder.get().subscribe(layer, publisherId);
225 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800226 throw e.rethrowFromSystemServer();
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700227 }
228 }
229
Mark Tabry16318e22019-03-22 10:04:32 -0700230 /**
231 * Start monitoring all messages for all layers, regardless of subscriptions.
232 */
Justin Pauporeccc75a32019-02-12 18:20:48 -0800233 public void startMonitoring() {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700234 verifySubscriptionIsAllowed();
235 try {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700236 mVmsSubscriberService.addVmsSubscriberPassive(mSubscriberManagerClient);
Asaf Rosenfeld2e45d812017-08-31 23:51:12 -0700237 VmsOperationRecorder.get().startMonitoring();
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800238 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800239 throw e.rethrowFromSystemServer();
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800240 }
241 }
242
243 /**
Mark Tabry16318e22019-03-22 10:04:32 -0700244 * Unsubscribes from data packets for a specific layer.
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800245 *
Mark Tabry16318e22019-03-22 10:04:32 -0700246 * @param layer layer to unsubscribe from
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700247 * @throws IllegalStateException if the client callback was not set via
Anna Linetsky40f1ded2018-05-07 16:37:01 -0700248 * {@link #setVmsSubscriberClientCallback}.
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800249 */
Mark Tabry16318e22019-03-22 10:04:32 -0700250 public void unsubscribe(@NonNull VmsLayer layer) {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700251 verifySubscriptionIsAllowed();
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800252 try {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700253 mVmsSubscriberService.removeVmsSubscriber(mSubscriberManagerClient, layer);
Demyn Plantenberg3ca12892017-06-20 21:01:34 -0700254 VmsOperationRecorder.get().unsubscribe(layer);
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800255 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800256 throw e.rethrowFromSystemServer();
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800257 }
258 }
259
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700260 /**
Mark Tabry16318e22019-03-22 10:04:32 -0700261 * Unsubscribes from data packets for a specific layer from a specific publisher.
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700262 *
Mark Tabry16318e22019-03-22 10:04:32 -0700263 * @param layer layer to unsubscribe from
264 * @param publisherId a publisher of the layer
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700265 * @throws IllegalStateException if the client callback was not set via
Anna Linetsky40f1ded2018-05-07 16:37:01 -0700266 * {@link #setVmsSubscriberClientCallback}.
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700267 */
Mark Tabry16318e22019-03-22 10:04:32 -0700268 public void unsubscribe(@NonNull VmsLayer layer, int publisherId) {
Antonio Cortes2ec3e352017-03-29 16:20:33 -0700269 try {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700270 mVmsSubscriberService.removeVmsSubscriberToPublisher(
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700271 mSubscriberManagerClient, layer, publisherId);
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700272 VmsOperationRecorder.get().unsubscribe(layer, publisherId);
273 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800274 throw e.rethrowFromSystemServer();
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700275 }
276 }
277
Mark Tabry16318e22019-03-22 10:04:32 -0700278 /**
279 * Stop monitoring. Only receive messages for layers which have been subscribed to."
280 */
Asaf Rosenfeld2e45d812017-08-31 23:51:12 -0700281 public void stopMonitoring() {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700282 try {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700283 mVmsSubscriberService.removeVmsSubscriberPassive(mSubscriberManagerClient);
Asaf Rosenfeld2e45d812017-08-31 23:51:12 -0700284 VmsOperationRecorder.get().stopMonitoring();
Antonio Cortes2ec3e352017-03-29 16:20:33 -0700285 } catch (RemoteException e) {
Justin Paupore0dd31772019-02-07 21:22:34 -0800286 throw e.rethrowFromSystemServer();
Antonio Cortes2ec3e352017-03-29 16:20:33 -0700287 }
288 }
289
Antonio Cortes01a60392017-03-22 13:00:02 -0700290 private void dispatchOnReceiveMessage(VmsLayer layer, byte[] payload) {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700291 VmsSubscriberClientCallback clientCallback = getClientCallbackThreadSafe();
292 if (clientCallback == null) {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700293 Log.e(TAG, "Cannot dispatch received message.");
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800294 return;
295 }
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700296 clientCallback.onVmsMessageReceived(layer, payload);
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800297 }
298
Asaf Rosenfeld908811e2018-01-22 09:13:47 -0800299 private void dispatchOnAvailabilityChangeMessage(VmsAvailableLayers availableLayers) {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700300 VmsSubscriberClientCallback clientCallback = getClientCallbackThreadSafe();
301 if (clientCallback == null) {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700302 Log.e(TAG, "Cannot dispatch availability change message.");
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700303 return;
304 }
Asaf Rosenfeld2e45d812017-08-31 23:51:12 -0700305 clientCallback.onLayersAvailabilityChanged(availableLayers);
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700306 }
307
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700308 private VmsSubscriberClientCallback getClientCallbackThreadSafe() {
309 VmsSubscriberClientCallback clientCallback;
310 synchronized (mClientCallbackLock) {
311 clientCallback = mClientCallback;
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700312 }
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700313 if (clientCallback == null) {
314 Log.e(TAG, "client callback not set.");
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700315 }
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700316 return clientCallback;
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700317 }
318
319 /*
320 * Verifies that the subscriber is in a state where it is allowed to subscribe.
321 */
322 private void verifySubscriptionIsAllowed() {
Asaf Rosenfelda0b665f2017-08-25 11:11:37 -0700323 VmsSubscriberClientCallback clientCallback = getClientCallbackThreadSafe();
324 if (clientCallback == null) {
Asaf Rosenfeld1a56ab92017-07-23 15:48:09 -0700325 throw new IllegalStateException("Cannot subscribe.");
326 }
327 }
328
329 /**
330 * @hide
331 */
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800332 @Override
333 public void onCarDisconnected() {
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800334 }
Antonio Cortesa7d8ed12017-02-02 11:50:01 -0800335}