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 
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.app.Service;
24 import android.car.Car;
25 import android.car.annotation.RequiredFeature;
26 import android.car.vms.VmsClientManager.VmsClientCallback;
27 import android.content.Intent;
28 import android.os.Binder;
29 import android.os.Handler;
30 import android.os.HandlerExecutor;
31 import android.os.IBinder;
32 import android.os.Looper;
33 import android.util.Log;
34 
35 import com.android.internal.annotations.GuardedBy;
36 import com.android.internal.annotations.VisibleForTesting;
37 
38 /**
39  * API implementation of a Vehicle Map Service publisher client.
40  *
41  * All publisher clients must inherit from this class and export it as a service, and the service
42  * be added to either the {@code vmsPublisherSystemClients} or {@code vmsPublisherUserClients}
43  * arrays in the Car service configuration, depending on which user the client will run as.
44  *
45  * The {@link com.android.car.VmsPublisherService} will then bind to this service, with the
46  * {@link #onVmsPublisherServiceReady()} callback notifying the client implementation when the
47  * connection is established and publisher operations can be called.
48  *
49  * Publishers must also register a publisher ID by calling {@link #getPublisherId(byte[])}.
50  *
51  * @deprecated Use {@link VmsClientManager} instead
52  * @hide
53  */
54 @RequiredFeature(Car.VEHICLE_MAP_SERVICE)
55 @Deprecated
56 @SystemApi
57 public abstract class VmsPublisherClientService extends Service {
58     private static final boolean DBG = false;
59     private static final String TAG = "VmsPublisherClientService";
60 
61 
62     private final Handler mHandler = new Handler(Looper.getMainLooper());
63     private final VmsClientCallback mClientCallback = new PublisherClientCallback();
64 
65     private final Object mLock = new Object();
66     @GuardedBy("mLock")
67     private @Nullable Car mCar;
68     @GuardedBy("mLock")
69     private @Nullable VmsClient mClient;
70 
71     @Override
onCreate()72     public void onCreate() {
73         if (DBG) Log.d(TAG, "Connecting to Car service");
74         synchronized (mLock) {
75             mCar = Car.createCar(this, mHandler, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
76                     this::onCarLifecycleChanged);
77         }
78     }
79 
80     @Override
onDestroy()81     public void onDestroy() {
82         if (DBG) Log.d(TAG, "Disconnecting from Car service");
83         synchronized (mLock) {
84             if (mCar != null) {
85                 mCar.disconnect();
86                 mCar = null;
87             }
88         }
89     }
90 
91     @Override
onBind(Intent intent)92     public IBinder onBind(Intent intent) {
93         if (DBG) Log.d(TAG, "onBind, intent: " + intent);
94         return new Binder();
95     }
96 
97     /**
98      * @hide
99      */
100     @VisibleForTesting
onCarLifecycleChanged(Car car, boolean ready)101     protected void onCarLifecycleChanged(Car car, boolean ready) {
102         if (DBG) Log.d(TAG, "Car service ready: " + ready);
103         if (ready) {
104             VmsClientManager clientManager =
105                     (VmsClientManager) car.getCarManager(Car.VEHICLE_MAP_SERVICE);
106             if (DBG) Log.d(TAG, "VmsClientManager: " + clientManager);
107             if (clientManager == null) {
108                 Log.e(TAG, "VmsClientManager is not available");
109                 return;
110             }
111             clientManager.registerVmsClientCallback(new HandlerExecutor(mHandler), mClientCallback,
112                     /* legacyClient= */ true);
113         }
114     }
115 
116     /**
117      * Notifies the client that publisher services are ready.
118      */
onVmsPublisherServiceReady()119     protected abstract void onVmsPublisherServiceReady();
120 
121     /**
122      * Notifies the client of changes in layer subscriptions.
123      *
124      * @param subscriptionState state of layer subscriptions
125      */
onVmsSubscriptionChange(@onNull VmsSubscriptionState subscriptionState)126     public abstract void onVmsSubscriptionChange(@NonNull VmsSubscriptionState subscriptionState);
127 
128     /**
129      * Publishes a data packet to subscribers.
130      *
131      * Publishers must only publish packets for the layers that they have made offerings for.
132      *
133      * @param layer       layer to publish to
134      * @param publisherId ID of the publisher publishing the message
135      * @param payload     data packet to be sent
136      * @throws IllegalStateException if publisher services are not available
137      */
publish(@onNull VmsLayer layer, int publisherId, byte[] payload)138     public final void publish(@NonNull VmsLayer layer, int publisherId, byte[] payload) {
139         getVmsClient().publishPacket(publisherId, layer, payload);
140     }
141 
142     /**
143      * Sets the layers offered by a specific publisher.
144      *
145      * @param offering layers being offered for subscription by the publisher
146      * @throws IllegalStateException if publisher services are not available
147      */
setLayersOffering(@onNull VmsLayersOffering offering)148     public final void setLayersOffering(@NonNull VmsLayersOffering offering) {
149         getVmsClient().setProviderOfferings(offering.getPublisherId(), offering.getDependencies());
150     }
151 
152     /**
153      * Acquires a publisher ID for a serialized publisher description.
154      *
155      * Multiple calls to this method with the same information will return the same publisher ID.
156      *
157      * @param publisherInfo serialized publisher description information, in a vendor-specific
158      *                      format
159      * @return a publisher ID for the given publisher description
160      * @throws IllegalStateException if publisher services are not available
161      */
getPublisherId(byte[] publisherInfo)162     public final int getPublisherId(byte[] publisherInfo) {
163         return getVmsClient().registerProvider(publisherInfo);
164     }
165 
166     /**
167      * Gets the state of layer subscriptions.
168      *
169      * @return state of layer subscriptions
170      * @throws IllegalStateException if publisher services are not available
171      */
getSubscriptions()172     public final VmsSubscriptionState getSubscriptions() {
173         return getVmsClient().getSubscriptionState();
174     }
175 
getVmsClient()176     private VmsClient getVmsClient() {
177         synchronized (mLock) {
178             if (mClient == null) {
179                 throw new IllegalStateException("VMS client connection is not ready");
180             }
181             return mClient;
182         }
183     }
184 
185     private class PublisherClientCallback implements VmsClientCallback {
186         @Override
onClientConnected(VmsClient client)187         public void onClientConnected(VmsClient client) {
188             synchronized (mLock) {
189                 mClient = client;
190             }
191             onVmsPublisherServiceReady();
192         }
193 
194         @Override
onSubscriptionStateChanged(VmsSubscriptionState subscriptionState)195         public void onSubscriptionStateChanged(VmsSubscriptionState subscriptionState) {
196             onVmsSubscriptionChange(subscriptionState);
197         }
198 
199         @Override
onLayerAvailabilityChanged(VmsAvailableLayers availableLayers)200         public void onLayerAvailabilityChanged(VmsAvailableLayers availableLayers) {
201             // Ignored
202         }
203 
204         @Override
onPacketReceived(int providerId, VmsLayer layer, byte[] packet)205         public void onPacketReceived(int providerId, VmsLayer layer, byte[] packet) {
206             // Does not subscribe to packets
207         }
208     }
209 }
210