summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CleanSpec.mk3
-rw-r--r--car-lib/src/android/car/Car.java28
-rw-r--r--car-lib/src/android/car/vms/IVmsPublisherClient.aidl40
-rw-r--r--car-lib/src/android/car/vms/IVmsPublisherService.aidl50
-rw-r--r--car-lib/src/android/car/vms/IVmsSubscriberClient.aidl32
-rw-r--r--car-lib/src/android/car/vms/IVmsSubscriberService.aidl96
-rw-r--r--car-lib/src/android/car/vms/VmsAssociatedLayer.aidl19
-rw-r--r--car-lib/src/android/car/vms/VmsAssociatedLayer.java101
-rw-r--r--car-lib/src/android/car/vms/VmsLayer.aidl19
-rw-r--r--car-lib/src/android/car/vms/VmsLayer.java126
-rw-r--r--car-lib/src/android/car/vms/VmsLayerDependency.aidl19
-rw-r--r--car-lib/src/android/car/vms/VmsLayerDependency.java97
-rw-r--r--car-lib/src/android/car/vms/VmsLayersOffering.aidl19
-rw-r--r--car-lib/src/android/car/vms/VmsLayersOffering.java89
-rw-r--r--car-lib/src/android/car/vms/VmsOperationRecorder.java227
-rw-r--r--car-lib/src/android/car/vms/VmsPublisherClientService.java282
-rw-r--r--car-lib/src/android/car/vms/VmsSubscriberManager.java377
-rw-r--r--car-lib/src/android/car/vms/VmsSubscriptionState.aidl19
-rw-r--r--car-lib/src/android/car/vms/VmsSubscriptionState.java120
-rw-r--r--service/AndroidManifest.xml11
-rw-r--r--service/res/values/config.xml7
-rw-r--r--service/res/values/strings.xml9
-rw-r--r--service/src/com/android/car/ICarImpl.java28
-rw-r--r--service/src/com/android/car/VmsLayersAvailability.java200
-rw-r--r--service/src/com/android/car/VmsPublisherService.java336
-rw-r--r--service/src/com/android/car/VmsPublishersInfo.java98
-rw-r--r--service/src/com/android/car/VmsRouting.java414
-rw-r--r--service/src/com/android/car/VmsSubscriberService.java353
-rw-r--r--service/src/com/android/car/hal/VehicleHal.java16
-rw-r--r--service/src/com/android/car/hal/VmsHalService.java850
-rw-r--r--tests/VmsPublisherClientSample/Android.mk37
-rw-r--r--tests/VmsPublisherClientSample/AndroidManifest.xml34
-rw-r--r--tests/VmsPublisherClientSample/res/mipmap-hdpi/ic_launcher.pngbin3418 -> 0 bytes
-rw-r--r--tests/VmsPublisherClientSample/res/mipmap-mdpi/ic_launcher.pngbin2206 -> 0 bytes
-rw-r--r--tests/VmsPublisherClientSample/res/mipmap-xhdpi/ic_launcher.pngbin4842 -> 0 bytes
-rw-r--r--tests/VmsPublisherClientSample/res/mipmap-xxhdpi/ic_launcher.pngbin7718 -> 0 bytes
-rw-r--r--tests/VmsPublisherClientSample/res/mipmap-xxxhdpi/ic_launcher.pngbin10486 -> 0 bytes
-rw-r--r--tests/VmsPublisherClientSample/res/values/strings.xml18
-rw-r--r--tests/VmsPublisherClientSample/src/com/google/android/car/vms/publisher/VmsPublisherClientSampleService.java81
-rw-r--r--tests/VmsSubscriberClientSample/Android.mk39
-rw-r--r--tests/VmsSubscriberClientSample/AndroidManifest.xml35
-rw-r--r--tests/VmsSubscriberClientSample/res/layout/activity_main.xml20
-rw-r--r--tests/VmsSubscriberClientSample/res/mipmap-hdpi/ic_launcher.pngbin3418 -> 0 bytes
-rw-r--r--tests/VmsSubscriberClientSample/res/mipmap-mdpi/ic_launcher.pngbin2206 -> 0 bytes
-rw-r--r--tests/VmsSubscriberClientSample/res/mipmap-xhdpi/ic_launcher.pngbin4842 -> 0 bytes
-rw-r--r--tests/VmsSubscriberClientSample/res/mipmap-xxhdpi/ic_launcher.pngbin7718 -> 0 bytes
-rw-r--r--tests/VmsSubscriberClientSample/res/mipmap-xxxhdpi/ic_launcher.pngbin10486 -> 0 bytes
-rw-r--r--tests/VmsSubscriberClientSample/res/values-w820dp/dimens.xml6
-rw-r--r--tests/VmsSubscriberClientSample/res/values/colors.xml6
-rw-r--r--tests/VmsSubscriberClientSample/res/values/dimens.xml5
-rw-r--r--tests/VmsSubscriberClientSample/res/values/strings.xml3
-rw-r--r--tests/VmsSubscriberClientSample/res/values/styles.xml8
-rw-r--r--tests/VmsSubscriberClientSample/res/xml/automotive_app_desc.xml20
-rw-r--r--tests/VmsSubscriberClientSample/src/com/google/android/car/vms/subscriber/VmsSubscriberClientSampleActivity.java113
-rw-r--r--tests/carservice_test/AndroidManifest.xml4
-rw-r--r--tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java40
-rw-r--r--tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java181
-rw-r--r--tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java245
-rw-r--r--tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java94
-rw-r--r--tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java195
-rw-r--r--tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java160
-rw-r--r--tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java238
-rw-r--r--tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java614
-rw-r--r--tests/carservice_test/src/com/android/car/test/VmsTestUtils.java16
-rw-r--r--tests/carservice_unit_test/src/com/android/car/VmsLayersAvailabilityTest.java266
-rw-r--r--tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java85
-rw-r--r--tests/carservice_unit_test/src/com/android/car/VmsRoutingTest.java309
67 files changed, 3 insertions, 6954 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index d828faa0..67d5bef3 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -57,6 +57,9 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/androi
57$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/src/android/car/hardware/ICarDiagnostic*.java) 57$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/src/android/car/hardware/ICarDiagnostic*.java)
58$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car7_intermediates/src/android/car/hardware/ICarDiagnostic*.java) 58$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car7_intermediates/src/android/car/hardware/ICarDiagnostic*.java)
59 59
60$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car7_intermediates/)
61$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android.car_intermediates/)
62
60# ************************************************ 63# ************************************************
61# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST 64# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
62# ************************************************ 65# ************************************************
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index c0b83f71..9a9e5312 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -32,7 +32,6 @@ import android.car.media.CarAudioManager;
32import android.car.navigation.CarNavigationStatusManager; 32import android.car.navigation.CarNavigationStatusManager;
33import android.car.CarBluetoothManager; 33import android.car.CarBluetoothManager;
34import android.car.test.CarTestManagerBinderWrapper; 34import android.car.test.CarTestManagerBinderWrapper;
35import android.car.vms.VmsSubscriberManager;
36import android.content.ComponentName; 35import android.content.ComponentName;
37import android.content.Context; 36import android.content.Context;
38import android.content.Intent; 37import android.content.Intent;
@@ -135,12 +134,6 @@ public final class Car {
135 public static final String BLUETOOTH_SERVICE = "car_bluetooth"; 134 public static final String BLUETOOTH_SERVICE = "car_bluetooth";
136 135
137 /** 136 /**
138 * @FutureFeature Cannot drop due to usage in non-flag protected place.
139 * @hide
140 */
141 public static final String VMS_SUBSCRIBER_SERVICE = "vehicle_map_subscriber_service";
142
143 /**
144 * Service for testing. This is system app only feature. 137 * Service for testing. This is system app only feature.
145 * Service name for {@link CarTestManager}, to be used in {@link #getCarManager(String)}. 138 * Service name for {@link CarTestManager}, to be used in {@link #getCarManager(String)}.
146 * @hide 139 * @hide
@@ -261,22 +254,6 @@ public final class Car {
261 "android.car.permission.CAR_TEST_SERVICE"; 254 "android.car.permission.CAR_TEST_SERVICE";
262 255
263 /** 256 /**
264 * Permissions necessary to access VMS publisher APIs.
265 *
266 * @hide
267 */
268 @FutureFeature
269 public static final String PERMISSION_VMS_PUBLISHER = "android.car.permission.VMS_PUBLISHER";
270
271 /**
272 * Permissions necessary to access VMS subscriber APIs.
273 *
274 * @hide
275 */
276 @FutureFeature
277 public static final String PERMISSION_VMS_SUBSCRIBER = "android.car.permission.VMS_SUBSCRIBER";
278
279 /**
280 * Permissions necessary to read diagnostic information, including vendor-specific bits. 257 * Permissions necessary to read diagnostic information, including vendor-specific bits.
281 * 258 *
282 * @hide 259 * @hide
@@ -654,11 +631,6 @@ public final class Car {
654 * only pass binder wrapper so that CarTestManager can be constructed outside. */ 631 * only pass binder wrapper so that CarTestManager can be constructed outside. */
655 manager = new CarTestManagerBinderWrapper(binder); 632 manager = new CarTestManagerBinderWrapper(binder);
656 break; 633 break;
657 case VMS_SUBSCRIBER_SERVICE:
658 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
659 manager = new VmsSubscriberManager(binder, mEventHandler);
660 }
661 break;
662 case BLUETOOTH_SERVICE: 634 case BLUETOOTH_SERVICE:
663 manager = new CarBluetoothManager(binder, mContext); 635 manager = new CarBluetoothManager(binder, mContext);
664 } 636 }
diff --git a/car-lib/src/android/car/vms/IVmsPublisherClient.aidl b/car-lib/src/android/car/vms/IVmsPublisherClient.aidl
deleted file mode 100644
index 96b993b3..00000000
--- a/car-lib/src/android/car/vms/IVmsPublisherClient.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
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
17package android.car.vms;
18
19import android.car.vms.IVmsPublisherService;
20import android.car.vms.VmsSubscriptionState;
21
22/**
23 * @hide
24 */
25interface IVmsPublisherClient {
26 /**
27 * Once the VmsPublisherService is bound to the client, this callback is used to set the
28 * binder that the client can use to invoke publisher services. This also gives the client
29 * the token it should use when calling the service.
30 */
31 oneway void setVmsPublisherService(in IBinder token, IVmsPublisherService service) = 0;
32
33 /**
34 * The VmsPublisherService uses this callback to notify about subscription changes.
35 * @param subscriptionState all the layers that have subscribers and a sequence number,
36 * clients should ignore any packet with a sequence number that is less
37 * than the highest sequence number they have seen thus far.
38 */
39 oneway void onVmsSubscriptionChange(in VmsSubscriptionState subscriptionState) = 1;
40}
diff --git a/car-lib/src/android/car/vms/IVmsPublisherService.aidl b/car-lib/src/android/car/vms/IVmsPublisherService.aidl
deleted file mode 100644
index 3c26a1b0..00000000
--- a/car-lib/src/android/car/vms/IVmsPublisherService.aidl
+++ /dev/null
@@ -1,50 +0,0 @@
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
17package android.car.vms;
18
19import android.car.vms.VmsLayer;
20import android.car.vms.VmsLayersOffering;
21import android.car.vms.VmsSubscriptionState;
22
23/**
24 * Exposes publisher services to VMS clients.
25 *
26 * @hide
27 */
28interface IVmsPublisherService {
29 /**
30 * Client call to publish a message.
31 */
32 oneway void publish(in IBinder token, in VmsLayer layer, int publisherId, in byte[] message) = 0;
33
34 /**
35 * Returns the list of VmsLayers that has any clients subscribed to it.
36 */
37 VmsSubscriptionState getSubscriptions() = 1;
38
39 /**
40 * Sets which layers the publisher can publish under which dependencties.
41 */
42 oneway void setLayersOffering(in IBinder token, in VmsLayersOffering offering) = 2;
43
44 /**
45 * The first time a publisher calls this API it will store the publisher info and assigns the
46 * publisher an ID. Between reboots, subsequent calls with the same publisher info will
47 * return the same ID so that a restarting process can obtain the same ID as it had before.
48 */
49 int getPublisherId(in byte[] publisherInfo) = 3;
50}
diff --git a/car-lib/src/android/car/vms/IVmsSubscriberClient.aidl b/car-lib/src/android/car/vms/IVmsSubscriberClient.aidl
deleted file mode 100644
index d5b56060..00000000
--- a/car-lib/src/android/car/vms/IVmsSubscriberClient.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
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
17package android.car.vms;
18
19import android.car.vms.VmsAssociatedLayer;
20import android.car.vms.VmsLayer;
21
22/**
23 * @hide
24 */
25oneway interface IVmsSubscriberClient {
26 /**
27 * A VmsService uses this callback to pass messages to subscribers.
28 */
29 void onVmsMessageReceived(in VmsLayer layer, in byte[] payload) = 0;
30
31 void onLayersAvailabilityChanged(in List<VmsAssociatedLayer> availableLayers) = 1;
32}
diff --git a/car-lib/src/android/car/vms/IVmsSubscriberService.aidl b/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
deleted file mode 100644
index d10a6e47..00000000
--- a/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
+++ /dev/null
@@ -1,96 +0,0 @@
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
17package android.car.vms;
18
19import android.car.vms.IVmsSubscriberClient;
20import android.car.vms.VmsLayer;
21
22/**
23 * @hide
24 */
25interface IVmsSubscriberService {
26 /**
27 * Adds a subscriber to notifications only.
28 * Should be called when a subscriber registers its callback, and before any subscription to a
29 * layer is made.
30 */
31 void addVmsSubscriberToNotifications(
32 in IVmsSubscriberClient subscriber) = 0;
33
34 /**
35 * Adds a subscriber to a VMS layer.
36 */
37 void addVmsSubscriber(
38 in IVmsSubscriberClient subscriber,
39 in VmsLayer layer) = 1;
40
41 /**
42 * Adds a subscriber to all actively broadcasted layers.
43 * Publishers will not be notified regarding this request so the state of the service will not
44 * change.
45 */
46 void addVmsSubscriberPassive(in IVmsSubscriberClient subscriber) = 2;
47
48 /**
49 * Adds a subscriber to a VMS layer from a specific publisher.
50 */
51 void addVmsSubscriberToPublisher(
52 in IVmsSubscriberClient subscriber,
53 in VmsLayer layer,
54 int publisherId) = 3;
55
56 /**
57    * Removes a subscriber to notifications only.
58 * Should be called when a subscriber unregisters its callback, and after all subscriptions to
59 * layers are removed.
60    */
61 void removeVmsSubscriberToNotifications(
62 in IVmsSubscriberClient subscriber) = 4;
63
64 /**
65    * Removes a subscriber to a VMS layer.
66    */
67 void removeVmsSubscriber(
68 in IVmsSubscriberClient subscriber,
69 in VmsLayer layer) = 5;
70
71 /**
72 * Removes a subscriber to all actively broadcasted layers.
73 * Publishers will not be notified regarding this request so the state of the service will not
74 * change.
75 */
76 void removeVmsSubscriberPassive(
77 in IVmsSubscriberClient subscriber) = 6;
78
79 /**
80 * Removes a subscriber to a VMS layer from a specific publisher.
81 */
82 void removeVmsSubscriberToPublisher(
83 in IVmsSubscriberClient subscriber,
84 in VmsLayer layer,
85 int publisherId) = 7;
86
87 /**
88 * Returns a list of available layers from the closure of the publishers offerings.
89 */
90 List<VmsLayer> getAvailableLayers() = 8;
91
92 /**
93 * Returns a the publisher information for a publisher ID.
94 */
95 byte[] getPublisherInfo(in int publisherId) = 9;
96}
diff --git a/car-lib/src/android/car/vms/VmsAssociatedLayer.aidl b/car-lib/src/android/car/vms/VmsAssociatedLayer.aidl
deleted file mode 100644
index c2cf2715..00000000
--- a/car-lib/src/android/car/vms/VmsAssociatedLayer.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
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
17package android.car.vms;
18
19parcelable VmsAssociatedLayer; \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsAssociatedLayer.java b/car-lib/src/android/car/vms/VmsAssociatedLayer.java
deleted file mode 100644
index 023fd9cb..00000000
--- a/car-lib/src/android/car/vms/VmsAssociatedLayer.java
+++ /dev/null
@@ -1,101 +0,0 @@
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
17package android.car.vms;
18
19import android.car.annotation.FutureFeature;
20import android.os.Parcel;
21import android.os.Parcelable;
22
23import java.util.*;
24
25/**
26 * A VMS Layer with a list of publisher IDs it is associated with.
27 *
28 * @hide
29 */
30@FutureFeature
31public final class VmsAssociatedLayer implements Parcelable {
32
33 // The VmsLayer.
34 private final VmsLayer mLayer;
35
36 // The IDs of the publishers that can publish this VmsLayer.
37 private final Set<Integer> mPublisherIds;
38
39 public VmsAssociatedLayer(VmsLayer layer, Set<Integer> publisherIds) {
40 mLayer = layer;
41 mPublisherIds = Collections.unmodifiableSet(publisherIds);
42 }
43
44 public VmsLayer getVmsLayer() {
45 return mLayer;
46 }
47
48 public Set<Integer> getPublisherIds() {
49 return mPublisherIds;
50 }
51
52 @Override
53 public String toString() {
54 return "VmsAssociatedLayer{ VmsLayer: " + mLayer + ", Publishers: " + mPublisherIds + "}";
55 }
56
57 // Parcelable related methods.
58 public static final Parcelable.Creator<VmsAssociatedLayer> CREATOR =
59 new Parcelable.Creator<VmsAssociatedLayer>() {
60 public VmsAssociatedLayer createFromParcel(Parcel in) {
61 return new VmsAssociatedLayer(in);
62 }
63
64 public VmsAssociatedLayer[] newArray(int size) {
65 return new VmsAssociatedLayer[size];
66 }
67 };
68
69 @Override
70 public void writeToParcel(Parcel out, int flags) {
71 out.writeParcelable(mLayer, flags);
72 out.writeArray(mPublisherIds.toArray());
73 }
74
75 @Override
76 public boolean equals(Object o) {
77 if (!(o instanceof VmsAssociatedLayer)) {
78 return false;
79 }
80 VmsAssociatedLayer p = (VmsAssociatedLayer) o;
81 return Objects.equals(p.mLayer, mLayer) && p.mPublisherIds.equals(mPublisherIds);
82 }
83
84 @Override
85 public int describeContents() {
86 return 0;
87 }
88
89 @Override
90 public int hashCode() {
91 return Objects.hash(mLayer, mPublisherIds);
92 }
93
94 private VmsAssociatedLayer(Parcel in) {
95 mLayer = in.readParcelable(VmsLayer.class.getClassLoader());
96
97 mPublisherIds = Collections.unmodifiableSet(
98 new HashSet<>(Arrays.asList(
99 (Integer[]) in.readArray(Integer.class.getClassLoader()))));
100 }
101} \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsLayer.aidl b/car-lib/src/android/car/vms/VmsLayer.aidl
deleted file mode 100644
index ff0768a3..00000000
--- a/car-lib/src/android/car/vms/VmsLayer.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
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
17package android.car.vms;
18
19parcelable VmsLayer; \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsLayer.java b/car-lib/src/android/car/vms/VmsLayer.java
deleted file mode 100644
index 9125796e..00000000
--- a/car-lib/src/android/car/vms/VmsLayer.java
+++ /dev/null
@@ -1,126 +0,0 @@
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
17package android.car.vms;
18
19import android.car.annotation.FutureFeature;
20import android.os.Parcel;
21import android.os.Parcelable;
22
23import java.util.Objects;
24
25/**
26 * A VMS Layer which can be subscribed to by VMS clients.
27 *
28 * @hide
29 */
30@FutureFeature
31public final class VmsLayer implements Parcelable {
32
33 // The layer Type.
34 private int mType;
35
36 // The layer Subtype.
37 private int mSubtype;
38
39 // The layer version.
40 private int mVersion;
41
42 public VmsLayer(int type, int subtype, int version) {
43 mType = type;
44 mSubtype = subtype;
45 mVersion = version;
46 }
47
48 public int getType() {
49 return mType;
50 }
51
52 public int getSubtype() {
53 return mSubtype;
54 }
55
56 public int getVersion() {
57 return mVersion;
58 }
59
60 /**
61 * Checks the two objects for equality by comparing their IDs and Versions.
62 *
63 * @param o the {@link VmsLayer} to which this one is to be checked for equality
64 * @return true if the underlying objects of the VmsLayer are both considered equal
65 */
66 @Override
67 public boolean equals(Object o) {
68 if (!(o instanceof VmsLayer)) {
69 return false;
70 }
71 VmsLayer p = (VmsLayer) o;
72 return Objects.equals(p.mType, mType) &&
73 Objects.equals(p.mSubtype, mSubtype) &&
74 Objects.equals(p.mVersion, mVersion);
75 }
76
77 /**
78 * Compute a hash code similarly tp {@link android.util.Pair}
79 *
80 * @return a hashcode of the Pair
81 */
82 @Override
83 public int hashCode() {
84 return Objects.hash(mType, mSubtype, mVersion);
85 }
86
87 @Override
88 public String toString() {
89 return "VmsLayer{ Type: " + mType + ", Sub type: " + mSubtype + ", Version: " + mVersion + "}";
90 }
91
92
93 // Parcelable related methods.
94 public static final Parcelable.Creator<VmsLayer> CREATOR = new
95 Parcelable.Creator<VmsLayer>() {
96 public VmsLayer createFromParcel(Parcel in) {
97 return new VmsLayer(in);
98 }
99
100 public VmsLayer[] newArray(int size) {
101 return new VmsLayer[size];
102 }
103 };
104
105 @Override
106 public void writeToParcel(Parcel out, int flags) {
107 out.writeInt(mType);
108 out.writeInt(mSubtype);
109 out.writeInt(mVersion);
110 }
111
112 @Override
113 public int describeContents() {
114 return 0;
115 }
116
117 private VmsLayer(Parcel in) {
118 readFromParcel(in);
119 }
120
121 private void readFromParcel(Parcel in) {
122 mType = in.readInt();
123 mSubtype = in.readInt();
124 mVersion = in.readInt();
125 }
126} \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsLayerDependency.aidl b/car-lib/src/android/car/vms/VmsLayerDependency.aidl
deleted file mode 100644
index 3e64001b..00000000
--- a/car-lib/src/android/car/vms/VmsLayerDependency.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
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
17package android.car.vms;
18
19parcelable VmsLayerDependency; \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsLayerDependency.java b/car-lib/src/android/car/vms/VmsLayerDependency.java
deleted file mode 100644
index 3b82775a..00000000
--- a/car-lib/src/android/car/vms/VmsLayerDependency.java
+++ /dev/null
@@ -1,97 +0,0 @@
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
17package android.car.vms;
18
19import android.car.annotation.FutureFeature;
20import android.os.Parcel;
21import android.os.Parcelable;
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.Collections;
25import java.util.HashSet;
26import java.util.List;
27import java.util.Set;
28
29/**
30 * A dependency for a VMS layer on other VMS layers.
31 *
32 * @hide
33 */
34@FutureFeature
35public final class VmsLayerDependency implements Parcelable {
36 private final VmsLayer mLayer;
37 private final Set<VmsLayer> mDependency;
38
39 /**
40 * Construct a dependency for layer on other layers.
41 */
42 public VmsLayerDependency(VmsLayer layer, Set<VmsLayer> dependencies) {
43 mLayer = layer;
44 mDependency = Collections.unmodifiableSet(dependencies);
45 }
46
47 /**
48 * Constructs a layer without a dependency.
49 */
50 public VmsLayerDependency(VmsLayer layer) {
51 mLayer = layer;
52 mDependency = Collections.emptySet();
53 }
54
55 public VmsLayer getLayer() {
56 return mLayer;
57 }
58
59 /**
60 * Returns the dependencies.
61 */
62 public Set<VmsLayer> getDependencies() {
63 return mDependency;
64 }
65
66 public static final Parcelable.Creator<VmsLayerDependency> CREATOR = new
67 Parcelable.Creator<VmsLayerDependency>() {
68 public VmsLayerDependency createFromParcel(Parcel in) {
69 return new VmsLayerDependency(in);
70 }
71 public VmsLayerDependency[] newArray(int size) {
72 return new VmsLayerDependency[size];
73 }
74 };
75
76 public String toString() {
77 return "VmsLayerDependency{ Layer: " + mLayer + " Dependency: " + mDependency + "}";
78 }
79
80 @Override
81 public void writeToParcel(Parcel out, int flags) {
82 out.writeParcelable(mLayer, flags);
83 out.writeParcelableList(new ArrayList<VmsLayer>(mDependency), flags);
84 }
85
86 @Override
87 public int describeContents() {
88 return 0;
89 }
90
91 private VmsLayerDependency(Parcel in) {
92 mLayer = in.readParcelable(VmsLayer.class.getClassLoader());
93 List<VmsLayer> dependency = new ArrayList<>();
94 in.readParcelableList(dependency, VmsLayer.class.getClassLoader());
95 mDependency = Collections.unmodifiableSet(new HashSet<VmsLayer>(dependency));
96 }
97} \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsLayersOffering.aidl b/car-lib/src/android/car/vms/VmsLayersOffering.aidl
deleted file mode 100644
index 4231f2da..00000000
--- a/car-lib/src/android/car/vms/VmsLayersOffering.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
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
17package android.car.vms;
18
19parcelable VmsLayersOffering; \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsLayersOffering.java b/car-lib/src/android/car/vms/VmsLayersOffering.java
deleted file mode 100644
index 6abffc60..00000000
--- a/car-lib/src/android/car/vms/VmsLayersOffering.java
+++ /dev/null
@@ -1,89 +0,0 @@
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
17package android.car.vms;
18
19import android.car.annotation.FutureFeature;
20import android.os.Parcel;
21import android.os.Parcelable;
22import java.util.ArrayList;
23import java.util.Collections;
24import java.util.HashSet;
25import java.util.List;
26import java.util.Set;
27
28/**
29 * The state of dependencies for a single publisher.
30 *
31 * @hide
32 */
33@FutureFeature
34public final class VmsLayersOffering implements Parcelable {
35
36 private final Set<VmsLayerDependency> mDependencies;
37
38 private final int mPublisherId;
39
40 public VmsLayersOffering(Set<VmsLayerDependency> dependencies, int publisherId) {
41 mDependencies = Collections.unmodifiableSet(dependencies);
42 mPublisherId = publisherId;
43 }
44
45 /**
46 * Returns the dependencies.
47 */
48 public Set<VmsLayerDependency> getDependencies() {
49 return mDependencies;
50 }
51
52 public int getPublisherId() {
53 return mPublisherId;
54 }
55
56 public static final Parcelable.Creator<VmsLayersOffering> CREATOR = new
57 Parcelable.Creator<VmsLayersOffering>() {
58 public VmsLayersOffering createFromParcel(Parcel in) {
59 return new VmsLayersOffering(in);
60 }
61 public VmsLayersOffering[] newArray(int size) {
62 return new VmsLayersOffering[size];
63 }
64 };
65
66 @Override
67 public String toString() {
68 return "VmsLayersOffering{" + mDependencies+ "}";
69 }
70
71 @Override
72 public void writeToParcel(Parcel out, int flags) {
73
74 out.writeParcelableList(new ArrayList(mDependencies), flags);
75 out.writeInt(mPublisherId);
76 }
77
78 @Override
79 public int describeContents() {
80 return 0;
81 }
82
83 private VmsLayersOffering(Parcel in) {
84 List<VmsLayerDependency> dependencies = new ArrayList<>();
85 in.readParcelableList(dependencies, VmsLayerDependency.class.getClassLoader());
86 mDependencies = Collections.unmodifiableSet(new HashSet<>(dependencies));
87 mPublisherId = in.readInt();
88 }
89} \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsOperationRecorder.java b/car-lib/src/android/car/vms/VmsOperationRecorder.java
deleted file mode 100644
index c873dce1..00000000
--- a/car-lib/src/android/car/vms/VmsOperationRecorder.java
+++ /dev/null
@@ -1,227 +0,0 @@
1package android.car.vms;
2
3import android.car.annotation.FutureFeature;
4import android.util.Log;
5
6import com.android.internal.annotations.VisibleForTesting;
7
8import org.json.JSONArray;
9import org.json.JSONException;
10import org.json.JSONObject;
11
12/**
13 * Records VMS operations using the Android Log.
14 *
15 * This class records VMS operations. The recorded messages include the VMS operations and its
16 * arguments encoded as JSON text so that the string can be both read as a log message and easily
17 * parsed. VmsOperationRecorder is intended to be called after successful state change.
18 *
19 * Access the VmsOperationRecorder using the {@link #get()} method, which returns a singleton
20 * instance. Each VMS operation has a corresponding VmsOperationRecorder method. For instance:
21 * <pre>{@code
22 * VmsOperationRecorder.get().subscribe(layer);
23 * }</pre>
24 *
25 * @hide
26 */
27@FutureFeature
28public final class VmsOperationRecorder {
29 private static final String TAG = "VmsOperationRecorder";
30 private static final VmsOperationRecorder INSTANCE = new VmsOperationRecorder(new Writer());
31 private final Writer mWriter;
32
33 @VisibleForTesting
34 public VmsOperationRecorder(Writer writer) {
35 mWriter = writer;
36 }
37
38 /** Return the singleton instance. */
39 public static VmsOperationRecorder get() {
40 return INSTANCE;
41 }
42
43 // VMS Client operations.
44
45 public void subscribe(VmsLayer layer) {
46 recordOp("subscribe", layer);
47 }
48
49 public void unsubscribe(VmsLayer layer) {
50 recordOp("unsubscribe", layer);
51 }
52
53 public void subscribe(VmsLayer layer, int publisherId) {
54 recordOp("subscribe", "publisherId", publisherId, layer);
55 }
56
57 public void unsubscribe(VmsLayer layer, int publisherId) {
58 recordOp("unsubscribe", "publisherId", publisherId, layer);
59 }
60
61 public void startMonitoring() {
62 recordOp("startMonitoring");
63 }
64
65 public void stopMonitoring() {
66 recordOp("stopMonitoring");
67 }
68
69 public void setLayersOffering(VmsLayersOffering layersOffering) {
70 recordOp("setLayersOffering", layersOffering);
71 }
72
73 public void getPublisherId(int publisherId) {
74 recordOp("getPublisherId", "publisherId", publisherId);
75 }
76
77 // VMS Service operations.
78
79 public void addSubscription(int sequenceNumber, VmsLayer layer) {
80 recordOp("addSubscription", "sequenceNumber", sequenceNumber, layer);
81 }
82
83 public void removeSubscription(int sequenceNumber, VmsLayer layer) {
84 recordOp("removeSubscription", "sequenceNumber", sequenceNumber, layer);
85 }
86
87 public void addPromiscuousSubscription(int sequenceNumber) {
88 recordOp("addPromiscuousSubscription", "sequenceNumber", sequenceNumber);
89 }
90
91 public void removePromiscuousSubscription(int sequenceNumber) {
92 recordOp("removePromiscuousSubscription", "sequenceNumber", sequenceNumber);
93 }
94
95 public void addHalSubscription(int sequenceNumber, VmsLayer layer) {
96 recordOp("addHalSubscription", "sequenceNumber", sequenceNumber, layer);
97 }
98
99 public void removeHalSubscription(int sequenceNumber, VmsLayer layer) {
100 recordOp("removeHalSubscription", "sequenceNumber", sequenceNumber, layer);
101 }
102
103 public void setPublisherLayersOffering(VmsLayersOffering layersOffering) {
104 recordOp("setPublisherLayersOffering", layersOffering);
105 }
106
107 public void setHalPublisherLayersOffering(VmsLayersOffering layersOffering) {
108 recordOp("setHalPublisherLayersOffering", layersOffering);
109 }
110
111 private void recordOp(String operation) {
112 if (isEnabled()) {
113 try {
114 write(new JSONObject().put(operation, new JSONObject()));
115 } catch (JSONException e) {
116 Log.e(TAG, e.toString());
117 }
118 }
119 }
120
121 private void recordOp(String operation, VmsLayer layer) {
122 if (isEnabled()) {
123 try {
124 recordOp(operation, new JSONObject().put("layer", toJson(layer)));
125 } catch (JSONException e) {
126 Log.e(TAG, e.toString());
127 }
128 }
129 }
130
131 private void recordOp(String operation, VmsLayersOffering layersOffering) {
132 if (isEnabled()) {
133 try {
134 JSONObject args = new JSONObject();
135 JSONArray offering = toJson(layersOffering);
136 if (offering.length() > 0) {
137 args.put("layerDependency", offering);
138 }
139 recordOp(operation, args);
140 } catch (JSONException e) {
141 Log.e(TAG, e.toString());
142 }
143 }
144 }
145
146 private void recordOp(String operation, String intArgName, int arg) {
147 if (isEnabled()) {
148 try {
149 recordOp(operation, new JSONObject().put(intArgName, arg));
150 } catch (JSONException e) {
151 Log.e(TAG, e.toString());
152 }
153 }
154 }
155
156 private void recordOp(String operation, String intArgName, int arg, VmsLayer layer) {
157 if (isEnabled()) {
158 try {
159 recordOp(operation,
160 new JSONObject().put(intArgName, arg).put("layer", toJson(layer)));
161 } catch (JSONException e) {
162 Log.e(TAG, e.toString());
163 }
164 }
165 }
166
167 private void recordOp(String operation, JSONObject args) {
168 if (isEnabled()) {
169 try {
170 write(new JSONObject().put(operation, args));
171 } catch (JSONException e) {
172 Log.e(TAG, e.toString());
173 }
174 }
175 }
176
177 private static JSONObject toJson(VmsLayer layer) throws JSONException {
178 return new JSONObject()
179 .put("type", layer.getType())
180 .put("subtype", layer.getSubtype())
181 .put("version", layer.getVersion());
182 }
183
184 private static JSONObject toJson(VmsLayerDependency layerDependency) throws JSONException {
185 JSONObject dep = new JSONObject();
186 dep.put("layer", toJson(layerDependency.getLayer()));
187 if (!layerDependency.getDependencies().isEmpty()) {
188 JSONArray dependencies = new JSONArray();
189 for (VmsLayer dependency : layerDependency.getDependencies()) {
190 dependencies.put(toJson(dependency));
191 }
192 dep.put("dependency", dependencies);
193 }
194 return dep;
195 }
196
197 private static JSONArray toJson(VmsLayersOffering layersOffering) throws JSONException {
198 JSONArray offerings = new JSONArray();
199 for (VmsLayerDependency layerDependency : layersOffering.getDependencies()) {
200 offerings.put(toJson(layerDependency));
201 }
202 return offerings;
203 }
204
205 private boolean isEnabled() {
206 return mWriter.isEnabled();
207 }
208
209 private void write(JSONObject object) {
210 mWriter.write(object.toString());
211 }
212
213 /** @hide */
214 @VisibleForTesting
215 public static class Writer {
216 private static final String TAG = "VMS.RECORD.EVENT";
217 private static final int LEVEL = Log.DEBUG;
218
219 public boolean isEnabled() {
220 return Log.isLoggable(TAG, LEVEL);
221 }
222
223 public void write(String msg) {
224 Log.println(LEVEL, TAG, msg);
225 }
226 }
227}
diff --git a/car-lib/src/android/car/vms/VmsPublisherClientService.java b/car-lib/src/android/car/vms/VmsPublisherClientService.java
deleted file mode 100644
index 33ca1f30..00000000
--- a/car-lib/src/android/car/vms/VmsPublisherClientService.java
+++ /dev/null
@@ -1,282 +0,0 @@
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
17package android.car.vms;
18
19
20import android.app.Service;
21import android.car.annotation.FutureFeature;
22import android.content.Intent;
23import android.os.Handler;
24import android.os.IBinder;
25import android.os.Looper;
26import android.os.Message;
27import android.os.RemoteException;
28import android.annotation.Nullable;
29import android.util.Log;
30
31import com.android.internal.annotations.GuardedBy;
32
33import java.lang.ref.WeakReference;
34
35/**
36 * Services that need VMS publisher services need to inherit from this class and also need to be
37 * declared in the array vmsPublisherClients located in
38 * packages/services/Car/service/res/values/config.xml (most likely, this file will be in an overlay
39 * of the target product.
40 *
41 * The {@link com.android.car.VmsPublisherService} will start this service. The callback
42 * {@link #onVmsPublisherServiceReady()} notifies when VMS publisher services can be used, and the
43 * publisher can request a publisher ID in order to start publishing.
44 *
45 * SystemApi candidate.
46 *
47 * @hide
48 */
49@FutureFeature
50public abstract class VmsPublisherClientService extends Service {
51 private static final boolean DBG = true;
52 private static final String TAG = "VmsPublisherClient";
53
54 private final Object mLock = new Object();
55
56 private Handler mHandler = new VmsEventHandler(this);
57 private final VmsPublisherClientBinder mVmsPublisherClient = new VmsPublisherClientBinder(this);
58 private volatile IVmsPublisherService mVmsPublisherService = null;
59 @GuardedBy("mLock")
60 private IBinder mToken = null;
61
62 @Override
63 public final IBinder onBind(Intent intent) {
64 if (DBG) {
65 Log.d(TAG, "onBind, intent: " + intent);
66 }
67 return mVmsPublisherClient.asBinder();
68 }
69
70 @Override
71 public final boolean onUnbind(Intent intent) {
72 if (DBG) {
73 Log.d(TAG, "onUnbind, intent: " + intent);
74 }
75 stopSelf();
76 return super.onUnbind(intent);
77 }
78
79 private void setToken(IBinder token) {
80 synchronized (mLock) {
81 mToken = token;
82 }
83 }
84
85 /**
86 * Notifies that the publisher services are ready.
87 */
88 protected abstract void onVmsPublisherServiceReady();
89
90 /**
91 * Publishers need to implement this method to receive notifications of subscription changes.
92 *
93 * @param subscriptionState the state of the subscriptions.
94 */
95 public abstract void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState);
96
97 /**
98 * Uses the VmsPublisherService binder to publish messages.
99 *
100 * @param layer the layer to publish to.
101 * @param payload the message to be sent.
102 * @param publisherId the ID that got assigned to the publisher that published the message by
103 * VMS core.
104 * @return if the call to the method VmsPublisherService.publish was successful.
105 */
106 public final void publish(VmsLayer layer, int publisherId, byte[] payload) {
107 if (DBG) {
108 Log.d(TAG, "Publishing for layer : " + layer);
109 }
110
111 IBinder token = getTokenForPublisherServiceThreadSafe();
112
113 try {
114 mVmsPublisherService.publish(token, layer, publisherId, payload);
115 } catch (RemoteException e) {
116 Log.e(TAG, "unable to publish message: " + payload, e);
117 }
118 }
119
120 /**
121 * Uses the VmsPublisherService binder to set the layers offering.
122 *
123 * @param offering the layers that the publisher may publish.
124 * @return if the call to VmsPublisherService.setLayersOffering was successful.
125 */
126 public final void setLayersOffering(VmsLayersOffering offering) {
127 if (DBG) {
128 Log.d(TAG, "Setting layers offering : " + offering);
129 }
130
131 IBinder token = getTokenForPublisherServiceThreadSafe();
132
133 try {
134 mVmsPublisherService.setLayersOffering(token, offering);
135 VmsOperationRecorder.get().setLayersOffering(offering);
136 } catch (RemoteException e) {
137 Log.e(TAG, "unable to set layers offering: " + offering, e);
138 }
139 }
140
141 private IBinder getTokenForPublisherServiceThreadSafe() {
142 if (mVmsPublisherService == null) {
143 throw new IllegalStateException("VmsPublisherService not set.");
144 }
145
146 IBinder token;
147 synchronized (mLock) {
148 token = mToken;
149 }
150 if (token == null) {
151 throw new IllegalStateException("VmsPublisherService does not have a valid token.");
152 }
153 return token;
154 }
155
156 public final int getPublisherId(byte[] publisherInfo) {
157 if (mVmsPublisherService == null) {
158 throw new IllegalStateException("VmsPublisherService not set.");
159 }
160 Integer publisherId = null;
161 try {
162 Log.i(TAG, "Getting publisher static ID");
163 publisherId = mVmsPublisherService.getPublisherId(publisherInfo);
164 } catch (RemoteException e) {
165 Log.e(TAG, "unable to invoke binder method.", e);
166 }
167 if (publisherId == null) {
168 throw new IllegalStateException("VmsPublisherService cannot get a publisher static ID.");
169 } else {
170 VmsOperationRecorder.get().getPublisherId(publisherId);
171 }
172 return publisherId;
173 }
174
175 /**
176 * Uses the VmsPublisherService binder to get the state of the subscriptions.
177 *
178 * @return list of layer/version or null in case of error.
179 */
180 public final @Nullable VmsSubscriptionState getSubscriptions() {
181 if (mVmsPublisherService == null) {
182 throw new IllegalStateException("VmsPublisherService not set.");
183 }
184 try {
185 return mVmsPublisherService.getSubscriptions();
186 } catch (RemoteException e) {
187 Log.e(TAG, "unable to invoke binder method.", e);
188 }
189 return null;
190 }
191
192 private void setVmsPublisherService(IVmsPublisherService service) {
193 mVmsPublisherService = service;
194 onVmsPublisherServiceReady();
195 }
196
197 /**
198 * Implements the interface that the VMS service uses to communicate with this client.
199 */
200 private static class VmsPublisherClientBinder extends IVmsPublisherClient.Stub {
201 private final WeakReference<VmsPublisherClientService> mVmsPublisherClientService;
202 @GuardedBy("mSequenceLock")
203 private long mSequence = -1;
204 private final Object mSequenceLock = new Object();
205
206 public VmsPublisherClientBinder(VmsPublisherClientService vmsPublisherClientService) {
207 mVmsPublisherClientService = new WeakReference<>(vmsPublisherClientService);
208 }
209
210 @Override
211 public void setVmsPublisherService(IBinder token, IVmsPublisherService service)
212 throws RemoteException {
213 VmsPublisherClientService vmsPublisherClientService = mVmsPublisherClientService.get();
214 if (vmsPublisherClientService == null) return;
215 if (DBG) {
216 Log.d(TAG, "setting VmsPublisherService.");
217 }
218 Handler handler = vmsPublisherClientService.mHandler;
219 handler.sendMessage(
220 handler.obtainMessage(VmsEventHandler.SET_SERVICE_CALLBACK, service));
221 vmsPublisherClientService.setToken(token);
222 }
223
224 @Override
225 public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState)
226 throws RemoteException {
227 VmsPublisherClientService vmsPublisherClientService = mVmsPublisherClientService.get();
228 if (vmsPublisherClientService == null) return;
229 if (DBG) {
230 Log.d(TAG, "subscription event: " + subscriptionState);
231 }
232 synchronized (mSequenceLock) {
233 if (subscriptionState.getSequenceNumber() <= mSequence) {
234 Log.w(TAG, "Sequence out of order. Current sequence = " + mSequence
235 + "; expected new sequence = " + subscriptionState.getSequenceNumber());
236 // Do not propagate old notifications.
237 return;
238 } else {
239 mSequence = subscriptionState.getSequenceNumber();
240 }
241 }
242 Handler handler = vmsPublisherClientService.mHandler;
243 handler.sendMessage(
244 handler.obtainMessage(VmsEventHandler.ON_SUBSCRIPTION_CHANGE_EVENT,
245 subscriptionState));
246 }
247 }
248
249 /**
250 * Receives events from the binder thread and dispatches them.
251 */
252 private final static class VmsEventHandler extends Handler {
253 /** Constants handled in the handler */
254 private static final int ON_SUBSCRIPTION_CHANGE_EVENT = 0;
255 private static final int SET_SERVICE_CALLBACK = 1;
256
257 private final WeakReference<VmsPublisherClientService> mVmsPublisherClientService;
258
259 VmsEventHandler(VmsPublisherClientService service) {
260 super(Looper.getMainLooper());
261 mVmsPublisherClientService = new WeakReference<>(service);
262 }
263
264 @Override
265 public void handleMessage(Message msg) {
266 VmsPublisherClientService service = mVmsPublisherClientService.get();
267 if (service == null) return;
268 switch (msg.what) {
269 case ON_SUBSCRIPTION_CHANGE_EVENT:
270 VmsSubscriptionState subscriptionState = (VmsSubscriptionState) msg.obj;
271 service.onVmsSubscriptionChange(subscriptionState);
272 break;
273 case SET_SERVICE_CALLBACK:
274 service.setVmsPublisherService((IVmsPublisherService) msg.obj);
275 break;
276 default:
277 Log.e(TAG, "Event type not handled: " + msg.what);
278 break;
279 }
280 }
281 }
282}
diff --git a/car-lib/src/android/car/vms/VmsSubscriberManager.java b/car-lib/src/android/car/vms/VmsSubscriberManager.java
deleted file mode 100644
index 6f6377ca..00000000
--- a/car-lib/src/android/car/vms/VmsSubscriberManager.java
+++ /dev/null
@@ -1,377 +0,0 @@
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
17package android.car.vms;
18
19import android.car.Car;
20import android.car.CarManagerBase;
21import android.car.CarNotConnectedException;
22import android.car.annotation.FutureFeature;
23import android.os.Handler;
24import android.os.IBinder;
25import android.os.Looper;
26import android.os.Message;
27import android.os.RemoteException;
28import android.util.Log;
29
30import com.android.internal.annotations.GuardedBy;
31
32import java.lang.ref.WeakReference;
33import java.util.List;
34
35/**
36 * API for interfacing with the VmsSubscriberService. It supports a single client callback that can
37 * (un)subscribe to different layers. Getting notifactions and managing subscriptions is enabled
38 * after setting the client callback with #registerClientCallback.
39 * SystemApi candidate
40 *
41 * @hide
42 */
43@FutureFeature
44public final class VmsSubscriberManager implements CarManagerBase {
45 private static final boolean DBG = true;
46 private static final String TAG = "VmsSubscriberManager";
47
48 private final Handler mHandler;
49 private final IVmsSubscriberService mVmsSubscriberService;
50 private final IVmsSubscriberClient mSubscriberManagerClient;
51 private final Object mClientCallbackLock = new Object();
52 @GuardedBy("mClientCallbackLock")
53 private VmsSubscriberClientCallback mClientCallback;
54
55 /**
56 * Interface exposed to VMS subscribers: it is a wrapper of IVmsSubscriberClient.
57 */
58 public interface VmsSubscriberClientCallback {
59 /**
60 * Called when the property is updated
61 */
62 void onVmsMessageReceived(VmsLayer layer, byte[] payload);
63
64 /**
65 * Called when layers availability change
66 */
67 void onLayersAvailabilityChanged(List<VmsLayer> availableLayers);
68 }
69
70 /**
71 * Allows to asynchronously dispatch onVmsMessageReceived events.
72 */
73 private final static class VmsEventHandler extends Handler {
74 /**
75 * Constants handled in the handler
76 */
77 private static final int ON_RECEIVE_MESSAGE_EVENT = 0;
78 private static final int ON_AVAILABILITY_CHANGE_EVENT = 1;
79
80 private final WeakReference<VmsSubscriberManager> mMgr;
81
82 VmsEventHandler(VmsSubscriberManager mgr, Looper looper) {
83 super(looper);
84 mMgr = new WeakReference<>(mgr);
85 }
86
87 @Override
88 public void handleMessage(Message msg) {
89 VmsSubscriberManager mgr = mMgr.get();
90 switch (msg.what) {
91 case ON_RECEIVE_MESSAGE_EVENT:
92 if (mgr != null) {
93 // Parse the message
94 VmsDataMessage vmsDataMessage = (VmsDataMessage) msg.obj;
95
96 // Dispatch the parsed message
97 mgr.dispatchOnReceiveMessage(vmsDataMessage.getLayer(),
98 vmsDataMessage.getPayload());
99 }
100 break;
101 case ON_AVAILABILITY_CHANGE_EVENT:
102 if (mgr != null) {
103 // Parse the message
104 List<VmsLayer> vmsAvailabilityChangeMessage = (List<VmsLayer>) msg.obj;
105
106 // Dispatch the parsed message
107 mgr.dispatchOnAvailabilityChangeMessage(vmsAvailabilityChangeMessage);
108 }
109 break;
110
111 default:
112 Log.e(VmsSubscriberManager.TAG, "Event type not handled: " + msg.what);
113 break;
114 }
115 }
116 }
117
118 public VmsSubscriberManager(IBinder service, Handler handler) {
119 mVmsSubscriberService = IVmsSubscriberService.Stub.asInterface(service);
120 mHandler = new VmsEventHandler(this, handler.getLooper());
121 mSubscriberManagerClient = new IVmsSubscriberClient.Stub() {
122 @Override
123 public void onVmsMessageReceived(VmsLayer layer, byte[] payload)
124 throws RemoteException {
125 // Create the data message
126 VmsDataMessage vmsDataMessage = new VmsDataMessage(layer, payload);
127 mHandler.sendMessage(
128 mHandler.obtainMessage(
129 VmsEventHandler.ON_RECEIVE_MESSAGE_EVENT,
130 vmsDataMessage));
131 }
132
133 @Override
134 public void onLayersAvailabilityChanged(List<VmsAssociatedLayer> availableLayers) {
135 mHandler.sendMessage(
136 mHandler.obtainMessage(
137 VmsEventHandler.ON_AVAILABILITY_CHANGE_EVENT,
138 availableLayers));
139 }
140 };
141 }
142
143 /**
144 * Registers the client callback in order to enable communication with the client.
145 * By registering, the client will start getting notifications, and will be able to subscribe
146 * to layers.
147 * <p>
148 *
149 * @param clientCallback subscriber callback that will handle onVmsMessageReceived events.
150 * @throws IllegalStateException if the client callback was already set.
151 */
152 public void registerClientCallback(VmsSubscriberClientCallback clientCallback)
153 throws CarNotConnectedException {
154 synchronized (mClientCallbackLock) {
155 if (mClientCallback != null) {
156 throw new IllegalStateException("Client callback is already configured.");
157 }
158 mClientCallback = clientCallback;
159 }
160 try {
161 mVmsSubscriberService.addVmsSubscriberToNotifications(mSubscriberManagerClient);
162 } catch (RemoteException e) {
163 Log.e(TAG, "Could not connect: ", e);
164 throw new CarNotConnectedException(e);
165 }
166 }
167
168 /**
169 * Unregisters the client callback which disables communication with the client.
170 * @throws CarNotConnectedException, IllegalStateException
171 */
172 public void unregisterClientCallback()
173 throws CarNotConnectedException {
174
175 try {
176 mVmsSubscriberService.removeVmsSubscriberToNotifications(mSubscriberManagerClient);
177 } catch (RemoteException e) {
178 Log.e(TAG, "Could not connect: ", e);
179 throw new CarNotConnectedException(e);
180 } catch (IllegalStateException e) {
181 Log.e(TAG, "Could not unsubscribe from notifications");
182 throw e;
183 }
184
185 synchronized (mClientCallbackLock) {
186 mClientCallback = null;
187 }
188 }
189
190 /**
191 * Returns a serialized publisher information for a publisher ID.
192 */
193 public byte[] getPublisherInfo(int publisherId)
194 throws CarNotConnectedException, IllegalStateException {
195 try {
196 return mVmsSubscriberService.getPublisherInfo(publisherId);
197 } catch (RemoteException e) {
198 Log.e(TAG, "Could not connect: ", e);
199 throw new CarNotConnectedException(e);
200 } catch (IllegalStateException ex) {
201 Car.checkCarNotConnectedExceptionFromCarService(ex);
202 throw new IllegalStateException(ex);
203 }
204 }
205
206 /**
207 * Subscribes to listen to the layer specified.
208 *
209 * @param layer the layer to subscribe to.
210 * @throws IllegalStateException if the client callback was not set via
211 * {@link #registerClientCallback}.
212 */
213 public void subscribe(VmsLayer layer) throws CarNotConnectedException {
214 verifySubscriptionIsAllowed();
215 try {
216 mVmsSubscriberService.addVmsSubscriber(mSubscriberManagerClient, layer);
217 VmsOperationRecorder.get().subscribe(layer);
218 } catch (RemoteException e) {
219 Log.e(TAG, "Could not connect: ", e);
220 throw new CarNotConnectedException(e);
221 } catch (IllegalStateException ex) {
222 Car.checkCarNotConnectedExceptionFromCarService(ex);
223 }
224 }
225
226 /**
227 * Subscribes to listen to the layer specified from the publisher specified.
228 *
229 * @param layer the layer to subscribe to.
230 * @param publisherId the publisher of the layer.
231 * @throws IllegalStateException if the client callback was not set via
232 * {@link #registerClientCallback}.
233 */
234 public void subscribe(VmsLayer layer, int publisherId) throws CarNotConnectedException {
235 verifySubscriptionIsAllowed();
236 try {
237 mVmsSubscriberService.addVmsSubscriberToPublisher(
238 mSubscriberManagerClient, layer, publisherId);
239 VmsOperationRecorder.get().subscribe(layer, publisherId);
240 } catch (RemoteException e) {
241 Log.e(TAG, "Could not connect: ", e);
242 throw new CarNotConnectedException(e);
243 } catch (IllegalStateException ex) {
244 Car.checkCarNotConnectedExceptionFromCarService(ex);
245 }
246 }
247
248 public void startMonitoring() throws CarNotConnectedException {
249 verifySubscriptionIsAllowed();
250 try {
251 mVmsSubscriberService.addVmsSubscriberPassive(mSubscriberManagerClient);
252 VmsOperationRecorder.get().startMonitoring();
253 } catch (RemoteException e) {
254 Log.e(TAG, "Could not connect: ", e);
255 throw new CarNotConnectedException(e);
256 } catch (IllegalStateException ex) {
257 Car.checkCarNotConnectedExceptionFromCarService(ex);
258 }
259 }
260
261 /**
262 * Unsubscribes from the layer/version specified.
263 *
264 * @param layer the layer to unsubscribe from.
265 * @throws IllegalStateException if the client callback was not set via
266 * {@link #registerClientCallback}.
267 */
268 public void unsubscribe(VmsLayer layer) {
269 verifySubscriptionIsAllowed();
270 try {
271 mVmsSubscriberService.removeVmsSubscriber(mSubscriberManagerClient, layer);
272 VmsOperationRecorder.get().unsubscribe(layer);
273 } catch (RemoteException e) {
274 Log.e(TAG, "Failed to unregister subscriber", e);
275 // ignore
276 } catch (IllegalStateException ex) {
277 Car.hideCarNotConnectedExceptionFromCarService(ex);
278 }
279 }
280
281 /**
282 * Unsubscribes from the layer/version specified.
283 *
284 * @param layer the layer to unsubscribe from.
285 * @param publisherId the pubisher of the layer.
286 * @throws IllegalStateException if the client callback was not set via
287 * {@link #registerClientCallback}.
288 */
289 public void unsubscribe(VmsLayer layer, int publisherId) {
290 try {
291 mVmsSubscriberService.removeVmsSubscriberToPublisher(
292 mSubscriberManagerClient, layer, publisherId);
293 VmsOperationRecorder.get().unsubscribe(layer, publisherId);
294 } catch (RemoteException e) {
295 Log.e(TAG, "Failed to unregister subscriber", e);
296 // ignore
297 } catch (IllegalStateException ex) {
298 Car.hideCarNotConnectedExceptionFromCarService(ex);
299 }
300 }
301
302 public void stopMonitoring() {
303 try {
304 mVmsSubscriberService.removeVmsSubscriberPassive(mSubscriberManagerClient);
305 VmsOperationRecorder.get().stopMonitoring();
306 } catch (RemoteException e) {
307 Log.e(TAG, "Failed to unregister subscriber ", e);
308 // ignore
309 } catch (IllegalStateException ex) {
310 Car.hideCarNotConnectedExceptionFromCarService(ex);
311 }
312 }
313
314 private void dispatchOnReceiveMessage(VmsLayer layer, byte[] payload) {
315 VmsSubscriberClientCallback clientCallback = getClientCallbackThreadSafe();
316 if (clientCallback == null) {
317 Log.e(TAG, "Cannot dispatch received message.");
318 return;
319 }
320 clientCallback.onVmsMessageReceived(layer, payload);
321 }
322
323 private void dispatchOnAvailabilityChangeMessage(List<VmsLayer> availableLayers) {
324 VmsSubscriberClientCallback clientCallback = getClientCallbackThreadSafe();
325 if (clientCallback == null) {
326 Log.e(TAG, "Cannot dispatch availability change message.");
327 return;
328 }
329 clientCallback.onLayersAvailabilityChanged(availableLayers);
330 }
331
332 private VmsSubscriberClientCallback getClientCallbackThreadSafe() {
333 VmsSubscriberClientCallback clientCallback;
334 synchronized (mClientCallbackLock) {
335 clientCallback = mClientCallback;
336 }
337 if (clientCallback == null) {
338 Log.e(TAG, "client callback not set.");
339 }
340 return clientCallback;
341 }
342
343 /*
344 * Verifies that the subscriber is in a state where it is allowed to subscribe.
345 */
346 private void verifySubscriptionIsAllowed() {
347 VmsSubscriberClientCallback clientCallback = getClientCallbackThreadSafe();
348 if (clientCallback == null) {
349 throw new IllegalStateException("Cannot subscribe.");
350 }
351 }
352
353 /**
354 * @hide
355 */
356 @Override
357 public void onCarDisconnected() {
358 }
359
360 private static final class VmsDataMessage {
361 private final VmsLayer mLayer;
362 private final byte[] mPayload;
363
364 public VmsDataMessage(VmsLayer layer, byte[] payload) {
365 mLayer = layer;
366 mPayload = payload;
367 }
368
369 public VmsLayer getLayer() {
370 return mLayer;
371 }
372
373 public byte[] getPayload() {
374 return mPayload;
375 }
376 }
377}
diff --git a/car-lib/src/android/car/vms/VmsSubscriptionState.aidl b/car-lib/src/android/car/vms/VmsSubscriptionState.aidl
deleted file mode 100644
index b5ce8fff..00000000
--- a/car-lib/src/android/car/vms/VmsSubscriptionState.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
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
17package android.car.vms;
18
19parcelable VmsSubscriptionState; \ No newline at end of file
diff --git a/car-lib/src/android/car/vms/VmsSubscriptionState.java b/car-lib/src/android/car/vms/VmsSubscriptionState.java
deleted file mode 100644
index ea433f70..00000000
--- a/car-lib/src/android/car/vms/VmsSubscriptionState.java
+++ /dev/null
@@ -1,120 +0,0 @@
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
17package android.car.vms;
18
19import android.car.annotation.FutureFeature;
20import android.os.Parcel;
21import android.os.Parcelable;
22
23import java.util.ArrayList;
24import java.util.Collections;
25import java.util.HashSet;
26import java.util.List;
27import java.util.Set;
28
29
30/**
31 * The list of layers with subscribers.
32 *
33 * @hide
34 */
35@FutureFeature
36public final class VmsSubscriptionState implements Parcelable {
37 private final int mSequenceNumber;
38 private final Set<VmsLayer> mLayers;
39 private final Set<VmsAssociatedLayer> mSubscribedLayersFromPublishers;
40
41 /**
42 * Construcs a summary of the state of the current subscriptions for publishers to consume
43 * and adjust which layers that the are publishing.
44 */
45 public VmsSubscriptionState(int sequenceNumber,
46 Set<VmsLayer> subscribedLayers,
47 Set<VmsAssociatedLayer> layersFromPublishers) {
48 mSequenceNumber = sequenceNumber;
49 mLayers = Collections.unmodifiableSet(subscribedLayers);
50 mSubscribedLayersFromPublishers = Collections.unmodifiableSet(layersFromPublishers);
51 }
52
53 /**
54 * Returns the sequence number assigned by the VMS service. Sequence numbers are
55 * monotonically increasing and help clients ignore potential out-of-order states.
56 */
57 public int getSequenceNumber() {
58 return mSequenceNumber;
59 }
60
61 public Set<VmsLayer> getLayers() {
62 return mLayers;
63 }
64
65 public Set<VmsAssociatedLayer> getAssociatedLayers() {
66 return mSubscribedLayersFromPublishers;
67 }
68
69 @Override
70 public String toString() {
71 StringBuilder sb = new StringBuilder();
72 sb.append("sequence number=").append(mSequenceNumber);
73 sb.append("; layers={");
74 for (VmsLayer layer : mLayers) {
75 sb.append(layer).append(",");
76 }
77 sb.append("}");
78 sb.append("; associatedLayers={");
79 for (VmsAssociatedLayer layer : mSubscribedLayersFromPublishers) {
80 sb.append(layer).append(",");
81 }
82 sb.append("}");
83 return sb.toString();
84 }
85
86 public static final Parcelable.Creator<VmsSubscriptionState> CREATOR = new
87 Parcelable.Creator<VmsSubscriptionState>() {
88 public VmsSubscriptionState createFromParcel(Parcel in) {
89 return new VmsSubscriptionState(in);
90 }
91
92 public VmsSubscriptionState[] newArray(int size) {
93 return new VmsSubscriptionState[size];
94 }
95 };
96
97 @Override
98 public void writeToParcel(Parcel out, int flags) {
99 out.writeInt(mSequenceNumber);
100 out.writeParcelableList(new ArrayList(mLayers), flags);
101 out.writeParcelableList(new ArrayList(mSubscribedLayersFromPublishers), flags);
102 }
103
104 @Override
105 public int describeContents() {
106 return 0;
107 }
108
109 private VmsSubscriptionState(Parcel in) {
110 mSequenceNumber = in.readInt();
111
112 List<VmsLayer> layers = new ArrayList<>();
113 in.readParcelableList(layers, VmsLayer.class.getClassLoader());
114 mLayers = Collections.unmodifiableSet(new HashSet(layers));
115
116 List<VmsAssociatedLayer> associatedLayers = new ArrayList<>();
117 in.readParcelableList(associatedLayers, VmsAssociatedLayer.class.getClassLoader());
118 mSubscribedLayersFromPublishers = Collections.unmodifiableSet(new HashSet(associatedLayers));
119 }
120} \ No newline at end of file
diff --git a/service/AndroidManifest.xml b/service/AndroidManifest.xml
index e39fb9ed..5c4dfaac 100644
--- a/service/AndroidManifest.xml
+++ b/service/AndroidManifest.xml
@@ -101,17 +101,6 @@
101 android:protectionLevel="system|signature" 101 android:protectionLevel="system|signature"
102 android:label="@string/car_permission_label_diag_clear" 102 android:label="@string/car_permission_label_diag_clear"
103 android:description="@string/car_permission_desc_diag_clear" /> 103 android:description="@string/car_permission_desc_diag_clear" />
104 <permission
105 android:name="android.car.permission.VMS_PUBLISHER"
106 android:protectionLevel="system|signature"
107 android:label="@string/car_permission_label_vms_publisher"
108 android:description="@string/car_permission_desc_vms_publisher" />
109 <permission
110 android:name="android.car.permission.VMS_SUBSCRIBER"
111 android:protectionLevel="system|signature"
112 android:label="@string/car_permission_label_vms_subscriber"
113 android:description="@string/car_permission_desc_vms_subscriber" />
114
115 <!-- may replace this with system permission if proper one is defined. --> 104 <!-- may replace this with system permission if proper one is defined. -->
116 <permission 105 <permission
117 android:name="android.car.permission.CONTROL_APP_BLOCKING" 106 android:name="android.car.permission.CONTROL_APP_BLOCKING"
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 61cef594..73028cba 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -74,11 +74,4 @@
74 <string name="defauiltActivityWhitelist">android,com.android.systemui</string> 74 <string name="defauiltActivityWhitelist">android,com.android.systemui</string>
75 <!-- Default home activity --> 75 <!-- Default home activity -->
76 <string name="defaultHomeActivity">com.android.car.overview/com.android.car.overview.StreamOverviewActivity</string> 76 <string name="defaultHomeActivity">com.android.car.overview/com.android.car.overview.StreamOverviewActivity</string>
77 <!-- The com.android.car.VmsPublisherService will bind to this list of clients -->
78 <string-array translatable="false" name="vmsPublisherClients">
79 </string-array>
80 <!-- Permissions that the com.android.car.VmsPublisherService is allowed to grant to publishers -->
81 <string-array translatable="false" name="vmsSafePermissions">
82 <item>"android.permission.ACCESS_FINE_LOCATION"</item>
83 </string-array>
84</resources> 77</resources>
diff --git a/service/res/values/strings.xml b/service/res/values/strings.xml
index 6cfff9a8..7f826d4c 100644
--- a/service/res/values/strings.xml
+++ b/service/res/values/strings.xml
@@ -116,13 +116,4 @@
116 <!-- Permission text: apps can clear diagnostic data from the car [CHAR LIMIT=NONE] --> 116 <!-- Permission text: apps can clear diagnostic data from the car [CHAR LIMIT=NONE] -->
117 <string name="car_permission_desc_diag_clear">Clear diagnostic data from the car</string> 117 <string name="car_permission_desc_diag_clear">Clear diagnostic data from the car</string>
118 118
119 <!-- Permission text: apps can publish VMS data [CHAR LIMIT=NONE] -->
120 <string name="car_permission_label_vms_publisher">VMS publisher</string>
121 <!-- Permission text: apps can send VMS messages to the car [CHAR LIMIT=NONE] -->
122 <string name="car_permission_desc_vms_publisher">Publish vms messages</string>
123
124 <!-- Permission text: apps can subscribe to VMS data [CHAR LIMIT=NONE] -->
125 <string name="car_permission_label_vms_subscriber">VMS subscriber</string>
126 <!-- Permission text: apps can receive VMS messages from the car [CHAR LIMIT=NONE] -->
127 <string name="car_permission_desc_vms_subscriber">Subscribe to vms messages</string>
128</resources> 119</resources>
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index bd424542..bbb86f60 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -72,10 +72,6 @@ public class ICarImpl extends ICar.Stub {
72 private final CarBluetoothService mCarBluetoothService; 72 private final CarBluetoothService mCarBluetoothService;
73 private final PerUserCarServiceHelper mPerUserCarServiceHelper; 73 private final PerUserCarServiceHelper mPerUserCarServiceHelper;
74 private CarDiagnosticService mCarDiagnosticService; 74 private CarDiagnosticService mCarDiagnosticService;
75 @FutureFeature
76 private VmsSubscriberService mVmsSubscriberService;
77 @FutureFeature
78 private VmsPublisherService mVmsPublisherService;
79 75
80 private final CarServiceBase[] mAllServices; 76 private final CarServiceBase[] mAllServices;
81 77
@@ -121,10 +117,6 @@ public class ICarImpl extends ICar.Stub {
121 mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext); 117 mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
122 mCarBluetoothService = new CarBluetoothService(serviceContext, mCarCabinService, 118 mCarBluetoothService = new CarBluetoothService(serviceContext, mCarCabinService,
123 mCarSensorService, mPerUserCarServiceHelper); 119 mCarSensorService, mPerUserCarServiceHelper);
124 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
125 mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
126 mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
127 }
128 mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal()); 120 mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());
129 121
130 // Be careful with order. Service depending on other service should be inited later. 122 // Be careful with order. Service depending on other service should be inited later.
@@ -150,10 +142,6 @@ public class ICarImpl extends ICar.Stub {
150 mCarDiagnosticService, 142 mCarDiagnosticService,
151 mPerUserCarServiceHelper 143 mPerUserCarServiceHelper
152 )); 144 ));
153 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
154 allServices.add(mVmsSubscriberService);
155 allServices.add(mVmsPublisherService);
156 }
157 mAllServices = allServices.toArray(new CarServiceBase[0]); 145 mAllServices = allServices.toArray(new CarServiceBase[0]);
158 } 146 }
159 147
@@ -233,12 +221,6 @@ public class ICarImpl extends ICar.Stub {
233 case Car.VENDOR_EXTENSION_SERVICE: 221 case Car.VENDOR_EXTENSION_SERVICE:
234 assertVendorExtensionPermission(mContext); 222 assertVendorExtensionPermission(mContext);
235 return mCarVendorExtensionService; 223 return mCarVendorExtensionService;
236 case Car.VMS_SUBSCRIBER_SERVICE:
237 FeatureUtil.assertFeature(FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE);
238 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
239 assertVmsSubscriberPermission(mContext);
240 return mVmsSubscriberService;
241 }
242 case Car.TEST_SERVICE: { 224 case Car.TEST_SERVICE: {
243 assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE); 225 assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE);
244 synchronized (this) { 226 synchronized (this) {
@@ -312,16 +294,6 @@ public class ICarImpl extends ICar.Stub {
312 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR); 294 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR);
313 } 295 }
314 296
315 @FutureFeature
316 public static void assertVmsPublisherPermission(Context context) {
317 assertPermission(context, Car.PERMISSION_VMS_PUBLISHER);
318 }
319
320 @FutureFeature
321 public static void assertVmsSubscriberPermission(Context context) {
322 assertPermission(context, Car.PERMISSION_VMS_SUBSCRIBER);
323 }
324
325 public static void assertPermission(Context context, String permission) { 297 public static void assertPermission(Context context, String permission) {
326 if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 298 if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
327 throw new SecurityException("requires " + permission); 299 throw new SecurityException("requires " + permission);
diff --git a/service/src/com/android/car/VmsLayersAvailability.java b/service/src/com/android/car/VmsLayersAvailability.java
deleted file mode 100644
index 93b917ca..00000000
--- a/service/src/com/android/car/VmsLayersAvailability.java
+++ /dev/null
@@ -1,200 +0,0 @@
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
17package com.android.car;
18
19import android.car.annotation.FutureFeature;
20import android.car.vms.VmsAssociatedLayer;
21import android.car.vms.VmsLayer;
22import android.car.vms.VmsLayerDependency;
23import android.car.vms.VmsLayersOffering;
24import android.util.Log;
25import com.android.internal.annotations.GuardedBy;
26
27import java.util.ArrayList;
28import java.util.Collection;
29import java.util.Collections;
30import java.util.HashMap;
31import java.util.HashSet;
32import java.util.List;
33import java.util.Map;
34import java.util.Set;
35import java.util.stream.Collectors;
36
37/**
38 * Manages VMS availability for layers.
39 * <p>
40 * Each VMS publisher sets its layers offering which are a list of layers the publisher claims
41 * it might publish. VmsLayersAvailability calculates from all the offering what are the
42 * available layers.
43 */
44
45@FutureFeature
46public class VmsLayersAvailability {
47
48 private static final boolean DBG = true;
49 private static final String TAG = "VmsLayersAvailability";
50
51 private final Object mLock = new Object();
52 @GuardedBy("mLock")
53 private final Map<VmsLayer, Set<Set<VmsLayer>>> mPotentialLayersAndDependencies =
54 new HashMap<>();
55 @GuardedBy("mLock")
56 private Set<VmsAssociatedLayer> mAvailableAssociatedLayers = Collections.EMPTY_SET;
57 @GuardedBy("mLock")
58 private Set<VmsAssociatedLayer> mUnavailableAssociatedLayers = Collections.EMPTY_SET;
59 @GuardedBy("mLock")
60 private Map<VmsLayer, Set<Integer>> mPotentialLayersAndPublishers = new HashMap<>();
61
62 /**
63 * Setting the current layers offerings as reported by publishers.
64 */
65 public void setPublishersOffering(Collection<VmsLayersOffering> publishersLayersOfferings) {
66 synchronized (mLock) {
67 reset();
68
69 for (VmsLayersOffering offering : publishersLayersOfferings) {
70 for (VmsLayerDependency dependency : offering.getDependencies()) {
71 VmsLayer layer = dependency.getLayer();
72
73 // Associate publishers with layers.
74 Set<Integer> curPotentialLayerAndPublishers =
75 mPotentialLayersAndPublishers.get(layer);
76 if (curPotentialLayerAndPublishers == null) {
77 curPotentialLayerAndPublishers = new HashSet<>();
78 mPotentialLayersAndPublishers.put(layer, curPotentialLayerAndPublishers);
79 }
80 curPotentialLayerAndPublishers.add(offering.getPublisherId());
81
82 // Add dependencies for availability calculation.
83 Set<Set<VmsLayer>> curDependencies =
84 mPotentialLayersAndDependencies.get(layer);
85 if (curDependencies == null) {
86 curDependencies = new HashSet<>();
87 mPotentialLayersAndDependencies.put(layer, curDependencies);
88 }
89 curDependencies.add(dependency.getDependencies());
90 }
91 }
92 calculateLayers();
93 }
94 }
95
96 /**
97 * Returns a collection of all the layers which may be published.
98 */
99 public Set<VmsAssociatedLayer> getAvailableLayers() {
100 synchronized (mLock) {
101 return mAvailableAssociatedLayers;
102 }
103 }
104
105 /**
106 * Returns a collection of all the layers which publishers could have published if the
107 * dependencies were satisfied.
108 */
109 public Set<VmsAssociatedLayer> getUnavailableLayers() {
110 synchronized (mLock) {
111 return mUnavailableAssociatedLayers;
112 }
113 }
114
115 private void reset() {
116 synchronized (mLock) {
117 mPotentialLayersAndDependencies.clear();
118 mPotentialLayersAndPublishers.clear();
119 mAvailableAssociatedLayers = Collections.EMPTY_SET;
120 mUnavailableAssociatedLayers = Collections.EMPTY_SET;
121 }
122 }
123
124 private void calculateLayers() {
125 synchronized (mLock) {
126 Set<VmsLayer> availableLayersSet = new HashSet<>();
127 Set<VmsLayer> cyclicAvoidanceAuxiliarySet = new HashSet<>();
128
129 for (VmsLayer layer : mPotentialLayersAndDependencies.keySet()) {
130 addLayerToAvailabilityCalculationLocked(layer,
131 availableLayersSet,
132 cyclicAvoidanceAuxiliarySet);
133 }
134
135 mAvailableAssociatedLayers = Collections.unmodifiableSet(
136 availableLayersSet
137 .stream()
138 .map(l -> new VmsAssociatedLayer(l, mPotentialLayersAndPublishers.get(l)))
139 .collect(Collectors.toSet()));
140
141 mUnavailableAssociatedLayers = Collections.unmodifiableSet(
142 mPotentialLayersAndDependencies.keySet()
143 .stream()
144 .filter(l -> !availableLayersSet.contains(l))
145 .map(l -> new VmsAssociatedLayer(l, mPotentialLayersAndPublishers.get(l)))
146 .collect(Collectors.toSet()));
147 }
148 }
149
150 private void addLayerToAvailabilityCalculationLocked(VmsLayer layer,
151 Set<VmsLayer> currentAvailableLayers,
152 Set<VmsLayer> cyclicAvoidanceSet) {
153 if (DBG) {
154 Log.d(TAG, "addLayerToAvailabilityCalculationLocked: checking layer: " + layer);
155 }
156 // If we already know that this layer is supported then we are done.
157 if (currentAvailableLayers.contains(layer)) {
158 return;
159 }
160 // If there is no offering for this layer we're done.
161 if (!mPotentialLayersAndDependencies.containsKey(layer)) {
162 return;
163 }
164 // Avoid cyclic dependency.
165 if (cyclicAvoidanceSet.contains(layer)) {
166 Log.e(TAG, "Detected a cyclic dependency: " + cyclicAvoidanceSet + " -> " + layer);
167 return;
168 }
169 // A layer may have multiple dependency sets. The layer is available if any dependency
170 // set is satisfied
171 for (Set<VmsLayer> dependencies : mPotentialLayersAndDependencies.get(layer)) {
172 // If layer does not have any dependencies then add to supported.
173 if (dependencies == null || dependencies.isEmpty()) {
174 currentAvailableLayers.add(layer);
175 return;
176 }
177 // Add the layer to cyclic avoidance set
178 cyclicAvoidanceSet.add(layer);
179
180 boolean isSupported = true;
181 for (VmsLayer dependency : dependencies) {
182 addLayerToAvailabilityCalculationLocked(dependency,
183 currentAvailableLayers,
184 cyclicAvoidanceSet);
185
186 if (!currentAvailableLayers.contains(dependency)) {
187 isSupported = false;
188 break;
189 }
190 }
191 cyclicAvoidanceSet.remove(layer);
192
193 if (isSupported) {
194 currentAvailableLayers.add(layer);
195 return;
196 }
197 }
198 return;
199 }
200}
diff --git a/service/src/com/android/car/VmsPublisherService.java b/service/src/com/android/car/VmsPublisherService.java
deleted file mode 100644
index 8a293e5e..00000000
--- a/service/src/com/android/car/VmsPublisherService.java
+++ /dev/null
@@ -1,336 +0,0 @@
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
17package com.android.car;
18
19import android.car.annotation.FutureFeature;
20import android.car.vms.IVmsSubscriberClient;
21import android.car.vms.IVmsPublisherClient;
22import android.car.vms.IVmsPublisherService;
23import android.car.vms.VmsLayer;
24import android.car.vms.VmsLayersOffering;
25import android.car.vms.VmsSubscriptionState;
26import android.content.ComponentName;
27import android.content.Context;
28import android.content.Intent;
29import android.content.ServiceConnection;
30import android.content.pm.PackageInfo;
31import android.content.pm.PackageManager;
32import android.os.Binder;
33import android.os.IBinder;
34import android.os.RemoteException;
35import android.os.UserHandle;
36import android.text.TextUtils;
37import android.util.Log;
38import com.android.car.hal.VmsHalService;
39import com.android.internal.annotations.GuardedBy;
40import java.io.PrintWriter;
41import java.lang.ref.WeakReference;
42import java.util.ArrayList;
43import java.util.Arrays;
44import java.util.HashMap;
45import java.util.HashSet;
46import java.util.List;
47import java.util.Map;
48import java.util.Set;
49
50/**
51 * + Receives HAL updates by implementing VmsHalService.VmsHalListener.
52 * + Binds to publishers and configures them to use this service.
53 * + Notifies publishers of subscription changes.
54 */
55@FutureFeature
56public class VmsPublisherService extends IVmsPublisherService.Stub
57 implements CarServiceBase, VmsHalService.VmsHalPublisherListener {
58 private static final boolean DBG = true;
59 private static final String TAG = "VmsPublisherService";
60
61 private final Context mContext;
62 private final VmsHalService mHal;
63 private final VmsPublisherManager mPublisherManager;
64 private Set<String> mSafePermissions;
65
66 public VmsPublisherService(Context context, VmsHalService hal) {
67 mContext = context;
68 mHal = hal;
69 mPublisherManager = new VmsPublisherManager(this);
70 }
71
72 // Implements CarServiceBase interface.
73 @Override
74 public void init() {
75 mHal.addPublisherListener(this);
76 // Load permissions that can be granted to publishers.
77 mSafePermissions = new HashSet<>(
78 Arrays.asList(mContext.getResources().getStringArray(R.array.vmsSafePermissions)));
79 // Launch publishers.
80 String[] publisherNames = mContext.getResources().getStringArray(
81 R.array.vmsPublisherClients);
82 for (String publisherName : publisherNames) {
83 if (TextUtils.isEmpty(publisherName)) {
84 Log.e(TAG, "empty publisher name");
85 continue;
86 }
87 ComponentName name = ComponentName.unflattenFromString(publisherName);
88 if (name == null) {
89 Log.e(TAG, "invalid publisher name: " + publisherName);
90 }
91 mPublisherManager.bind(name);
92 }
93 }
94
95 @Override
96 public void release() {
97 mPublisherManager.release();
98 mHal.removePublisherListener(this);
99 }
100
101 @Override
102 public void dump(PrintWriter writer) {
103 }
104
105 @Override
106 public void setLayersOffering(IBinder token, VmsLayersOffering offering) {
107 mHal.setPublisherLayersOffering(token, offering);
108 }
109
110 // Implements IVmsPublisherService interface.
111 @Override
112 public void publish(IBinder token, VmsLayer layer, int publisherId, byte[] payload) {
113 if (DBG) {
114 Log.d(TAG, "Publishing for layer: " + layer);
115 }
116 ICarImpl.assertVmsPublisherPermission(mContext);
117
118 // Send the message to application listeners.
119 Set<IVmsSubscriberClient> listeners =
120 mHal.getSubscribersForLayerFromPublisher(layer, publisherId);
121
122 if (DBG) {
123 Log.d(TAG, "Number of subscribed apps: " + listeners.size());
124 }
125 for (IVmsSubscriberClient listener : listeners) {
126 try {
127 listener.onVmsMessageReceived(layer, payload);
128 } catch (RemoteException ex) {
129 Log.e(TAG, "unable to publish to listener: " + listener);
130 }
131 }
132
133 // Send the message to HAL
134 if (mHal.isHalSubscribed(layer)) {
135 Log.d(TAG, "HAL is subscribed");
136 mHal.setDataMessage(layer, payload);
137 } else {
138 Log.d(TAG, "HAL is NOT subscribed");
139 }
140 }
141
142 @Override
143 public VmsSubscriptionState getSubscriptions() {
144 ICarImpl.assertVmsPublisherPermission(mContext);
145 return mHal.getSubscriptionState();
146 }
147
148 @Override
149 public int getPublisherId(byte[] publisherInfo) {
150 ICarImpl.assertVmsPublisherPermission(mContext);
151 return mHal.getPublisherId(publisherInfo);
152 }
153
154 // Implements VmsHalListener interface
155 /**
156 * This method is only invoked by VmsHalService.notifyPublishers which is synchronized.
157 * Therefore this method only sees a non-decreasing sequence.
158 */
159 @Override
160 public void onChange(VmsSubscriptionState subscriptionState) {
161 // Send the message to application listeners.
162 for (IVmsPublisherClient client : mPublisherManager.getClients()) {
163 try {
164 client.onVmsSubscriptionChange(subscriptionState);
165 } catch (RemoteException ex) {
166 Log.e(TAG, "unable to send notification to: " + client, ex);
167 }
168 }
169 }
170
171 /**
172 * Keeps track of publishers that are using this service.
173 */
174 private static class VmsPublisherManager {
175 /**
176 * Allows to modify mPublisherMap and mPublisherConnectionMap as a single unit.
177 */
178 private final Object mLock = new Object();
179 @GuardedBy("mLock")
180 private final Map<String, PublisherConnection> mPublisherConnectionMap = new HashMap<>();
181 @GuardedBy("mLock")
182 private final Map<String, IVmsPublisherClient> mPublisherMap = new HashMap<>();
183 private final WeakReference<VmsPublisherService> mPublisherService;
184
185 public VmsPublisherManager(VmsPublisherService publisherService) {
186 mPublisherService = new WeakReference<>(publisherService);
187 }
188
189 /**
190 * Tries to bind to a publisher.
191 *
192 * @param name publisher component name (e.g. android.car.vms.logger/.LoggingService).
193 */
194 public void bind(ComponentName name) {
195 VmsPublisherService publisherService = mPublisherService.get();
196 if (publisherService == null) return;
197 String publisherName = name.flattenToString();
198 if (DBG) {
199 Log.d(TAG, "binding to: " + publisherName);
200 }
201 synchronized (mLock) {
202 if (mPublisherConnectionMap.containsKey(publisherName)) {
203 // Already registered, nothing to do.
204 return;
205 }
206 grantPermissions(name);
207 Intent intent = new Intent();
208 intent.setComponent(name);
209 PublisherConnection connection = new PublisherConnection();
210 if (publisherService.mContext.bindServiceAsUser(intent, connection,
211 Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
212 mPublisherConnectionMap.put(publisherName, connection);
213 } else {
214 Log.e(TAG, "unable to bind to: " + publisherName);
215 }
216 }
217 }
218
219 /**
220 * Removes the publisher and associated connection.
221 *
222 * @param name publisher component name (e.g. android.car.vms.Logger).
223 */
224 public void unbind(ComponentName name) {
225 VmsPublisherService publisherService = mPublisherService.get();
226 if (publisherService == null) return;
227 String publisherName = name.flattenToString();
228 if (DBG) {
229 Log.d(TAG, "unbinding from: " + publisherName);
230 }
231 synchronized (mLock) {
232 boolean found = mPublisherMap.remove(publisherName) != null;
233 if (found) {
234 PublisherConnection connection = mPublisherConnectionMap.get(publisherName);
235 publisherService.mContext.unbindService(connection);
236 mPublisherConnectionMap.remove(publisherName);
237 } else {
238 Log.e(TAG, "unbind: unknown publisher." + publisherName);
239 }
240 }
241 }
242
243 /**
244 * Returns the list of publishers currently registered.
245 *
246 * @return list of publishers.
247 */
248 public List<IVmsPublisherClient> getClients() {
249 synchronized (mLock) {
250 return new ArrayList<>(mPublisherMap.values());
251 }
252 }
253
254 public void release() {
255 VmsPublisherService publisherService = mPublisherService.get();
256 if (publisherService == null) return;
257 for (PublisherConnection connection : mPublisherConnectionMap.values()) {
258 publisherService.mContext.unbindService(connection);
259 }
260 mPublisherConnectionMap.clear();
261 mPublisherMap.clear();
262 }
263
264 private void grantPermissions(ComponentName component) {
265 VmsPublisherService publisherService = mPublisherService.get();
266 if (publisherService == null) return;
267 final PackageManager packageManager = publisherService.mContext.getPackageManager();
268 final String packageName = component.getPackageName();
269 PackageInfo packageInfo;
270 try {
271 packageInfo = packageManager.getPackageInfo(packageName,
272 PackageManager.GET_PERMISSIONS);
273 } catch (PackageManager.NameNotFoundException e) {
274 Log.e(TAG, "Error getting package info for " + packageName, e);
275 return;
276 }
277 if (packageInfo.requestedPermissions == null) return;
278 for (String permission : packageInfo.requestedPermissions) {
279 if (!publisherService.mSafePermissions.contains(permission)) {
280 continue;
281 }
282 if (packageManager.checkPermission(permission, packageName)
283 == PackageManager.PERMISSION_GRANTED) {
284 continue;
285 }
286 try {
287 packageManager.grantRuntimePermission(packageName, permission,
288 UserHandle.SYSTEM);
289 Log.d(TAG, "Permission " + permission + " granted to " + packageName);
290 } catch (SecurityException | IllegalArgumentException e) {
291 Log.e(TAG, "Error while trying to grant " + permission + " to " + packageName,
292 e);
293 }
294 }
295 }
296
297 class PublisherConnection implements ServiceConnection {
298
299 private final IBinder mToken = new Binder();
300
301 /**
302 * Once the service binds to a publisher service, the publisher binder is added to
303 * mPublisherMap
304 * and the publisher is configured to use this service.
305 */
306 @Override
307 public void onServiceConnected(ComponentName name, IBinder binder) {
308 VmsPublisherService publisherService = mPublisherService.get();
309 if (publisherService == null) return;
310 if (DBG) {
311 Log.d(TAG, "onServiceConnected, name: " + name + ", binder: " + binder);
312 }
313 IVmsPublisherClient service = IVmsPublisherClient.Stub.asInterface(binder);
314 synchronized (mLock) {
315 mPublisherMap.put(name.flattenToString(), service);
316 }
317 try {
318 service.setVmsPublisherService(mToken, publisherService);
319 } catch (RemoteException e) {
320 Log.e(TAG, "unable to configure publisher: " + name);
321 }
322 }
323
324 /**
325 * Tries to rebind to the publisher service.
326 */
327 @Override
328 public void onServiceDisconnected(ComponentName name) {
329 String publisherName = name.flattenToString();
330 Log.d(TAG, "onServiceDisconnected, name: " + publisherName);
331 VmsPublisherManager.this.unbind(name);
332 VmsPublisherManager.this.bind(name);
333 }
334 }
335 }
336}
diff --git a/service/src/com/android/car/VmsPublishersInfo.java b/service/src/com/android/car/VmsPublishersInfo.java
deleted file mode 100644
index 04ee82f7..00000000
--- a/service/src/com/android/car/VmsPublishersInfo.java
+++ /dev/null
@@ -1,98 +0,0 @@
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
17package com.android.car;
18
19
20import android.car.annotation.FutureFeature;
21import java.util.HashMap;
22import java.util.Map;
23import java.util.List;
24import java.util.ArrayList;
25import java.util.Arrays;
26import com.android.internal.annotations.GuardedBy;
27import android.util.Log;
28
29@FutureFeature
30public class VmsPublishersInfo {
31 private static final String TAG = "VmsPublishersInfo";
32 private static final boolean DBG = true;
33 private final Object mLock = new Object();
34 @GuardedBy("mLock")
35 private final Map<InfoWrapper, Integer> mPublishersIds = new HashMap();
36 @GuardedBy("mLock")
37 private final Map<Integer, byte[]> mPublishersInfo = new HashMap();
38
39 private static class InfoWrapper {
40 private final byte[] mInfo;
41
42 public InfoWrapper(byte[] info) {
43 mInfo = info;
44 }
45
46 public byte[] getInfo() {
47 return mInfo;
48 }
49
50 @Override
51 public boolean equals(Object o) {
52 if (!(o instanceof InfoWrapper)) {
53 return false;
54 }
55 InfoWrapper p = (InfoWrapper) o;
56 return Arrays.equals(this.mInfo, p.mInfo);
57 }
58
59 @Override
60 public int hashCode() {
61 return Arrays.hashCode(mInfo);
62 }
63 }
64
65 /**
66 * Returns the ID associated with the publisher info. When called for the first time for a
67 * publisher info will store the info and assign an ID
68 */
69 public int getIdForInfo(byte[] publisherInfo) {
70 Integer publisherId;
71 InfoWrapper wrappedPublisherInfo = new InfoWrapper(publisherInfo);
72 synchronized (mLock) {
73 maybeAddPublisherInfoLocked(wrappedPublisherInfo);
74 publisherId = mPublishersIds.get(wrappedPublisherInfo);
75 }
76 if (DBG) {
77 Log.i(TAG, "Publisher ID is: " + publisherId);
78 }
79 return publisherId;
80 }
81
82 public byte[] getPublisherInfo(int publisherId) {
83 synchronized (mLock) {
84 return mPublishersInfo.get(publisherId).clone();
85 }
86 }
87
88 private void maybeAddPublisherInfoLocked(InfoWrapper wrappedPublisherInfo) {
89 if (!mPublishersIds.containsKey(wrappedPublisherInfo)) {
90 // Assign ID to the info
91 Integer publisherId = mPublishersIds.size();
92
93 mPublishersIds.put(wrappedPublisherInfo, publisherId);
94 mPublishersInfo.put(publisherId, wrappedPublisherInfo.getInfo());
95 }
96 }
97}
98
diff --git a/service/src/com/android/car/VmsRouting.java b/service/src/com/android/car/VmsRouting.java
deleted file mode 100644
index 2e66781d..00000000
--- a/service/src/com/android/car/VmsRouting.java
+++ /dev/null
@@ -1,414 +0,0 @@
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
17package com.android.car;
18
19import android.car.annotation.FutureFeature;
20import android.car.vms.IVmsSubscriberClient;
21import android.car.vms.VmsAssociatedLayer;
22import android.car.vms.VmsLayer;
23import android.car.vms.VmsOperationRecorder;
24import android.car.vms.VmsSubscriptionState;
25
26import com.android.internal.annotations.GuardedBy;
27
28import java.util.ArrayList;
29import java.util.HashMap;
30import java.util.HashSet;
31import java.util.List;
32import java.util.Map;
33import java.util.Set;
34import java.util.stream.Collectors;
35
36/**
37 * Manages all the VMS subscriptions:
38 * + Subscriptions to data messages of individual layer + version.
39 * + Subscriptions to all data messages.
40 * + HAL subscriptions to layer + version.
41 */
42@FutureFeature
43public class VmsRouting {
44 private final Object mLock = new Object();
45 // A map of Layer + Version to subscribers.
46 @GuardedBy("mLock")
47 private Map<VmsLayer, Set<IVmsSubscriberClient>> mLayerSubscriptions = new HashMap<>();
48
49 @GuardedBy("mLock")
50 private Map<VmsLayer, Map<Integer, Set<IVmsSubscriberClient>>> mLayerSubscriptionsToPublishers =
51 new HashMap<>();
52 // A set of subscribers that are interested in any layer + version.
53 @GuardedBy("mLock")
54 private Set<IVmsSubscriberClient> mPromiscuousSubscribers = new HashSet<>();
55
56 // A set of all the layers + versions the HAL is subscribed to.
57 @GuardedBy("mLock")
58 private Set<VmsLayer> mHalSubscriptions = new HashSet<>();
59
60 @GuardedBy("mLock")
61 private Map<VmsLayer, Set<Integer>> mHalSubscriptionsToPublishers = new HashMap<>();
62 // A sequence number that is increased every time the subscription state is modified. Note that
63 // modifying the list of promiscuous subscribers does not affect the subscription state.
64 @GuardedBy("mLock")
65 private int mSequenceNumber = 0;
66
67 /**
68 * Add a subscriber subscription to data messages from a VMS layer.
69 *
70 * @param subscriber a VMS subscriber.
71 * @param layer the layer subscribing to.
72 */
73 public void addSubscription(IVmsSubscriberClient subscriber, VmsLayer layer) {
74 //TODO(b/36902947): revise if need to sync, and return value.
75 synchronized (mLock) {
76 ++mSequenceNumber;
77 // Get or create the list of subscribers for layer and version.
78 Set<IVmsSubscriberClient> subscribers = mLayerSubscriptions.get(layer);
79
80 if (subscribers == null) {
81 subscribers = new HashSet<>();
82 mLayerSubscriptions.put(layer, subscribers);
83 }
84 // Add the subscriber to the list.
85 subscribers.add(subscriber);
86 VmsOperationRecorder.get().addSubscription(mSequenceNumber, layer);
87 }
88 }
89
90 /**
91 * Add a subscriber subscription to all data messages.
92 *
93 * @param subscriber a VMS subscriber.
94 */
95 public void addSubscription(IVmsSubscriberClient subscriber) {
96 synchronized (mLock) {
97 ++mSequenceNumber;
98 mPromiscuousSubscribers.add(subscriber);
99 VmsOperationRecorder.get().addPromiscuousSubscription(mSequenceNumber);
100 }
101 }
102
103 /**
104 * Add a subscriber subscription to data messages from a VMS layer from a specific publisher.
105 *
106 * @param subscriber a VMS subscriber.
107 * @param layer the layer to subscribing to.
108 * @param publisherId the publisher ID.
109 */
110 public void addSubscription(IVmsSubscriberClient subscriber, VmsLayer layer, int publisherId) {
111 synchronized (mLock) {
112 ++mSequenceNumber;
113
114 Map<Integer, Set<IVmsSubscriberClient>> publisherIdsToSubscribersForLayer =
115 mLayerSubscriptionsToPublishers.get(layer);
116
117 if (publisherIdsToSubscribersForLayer == null) {
118 publisherIdsToSubscribersForLayer = new HashMap<>();
119 mLayerSubscriptionsToPublishers.put(layer, publisherIdsToSubscribersForLayer);
120 }
121
122 Set<IVmsSubscriberClient> subscribersForPublisher =
123 publisherIdsToSubscribersForLayer.get(publisherId);
124
125 if (subscribersForPublisher == null) {
126 subscribersForPublisher = new HashSet<>();
127 publisherIdsToSubscribersForLayer.put(publisherId, subscribersForPublisher);
128 }
129
130 // Add the subscriber to the list.
131 subscribersForPublisher.add(subscriber);
132 }
133 }
134
135 /**
136 * Remove a subscription for a layer + version and make sure to remove the key if there are no
137 * more subscribers.
138 *
139 * @param subscriber to remove.
140 * @param layer of the subscription.
141 */
142 public void removeSubscription(IVmsSubscriberClient subscriber, VmsLayer layer) {
143 synchronized (mLock) {
144 ++mSequenceNumber;
145 Set<IVmsSubscriberClient> subscribers = mLayerSubscriptions.get(layer);
146
147 // If there are no subscribers we are done.
148 if (subscribers == null) {
149 return;
150 }
151 subscribers.remove(subscriber);
152 VmsOperationRecorder.get().removeSubscription(mSequenceNumber, layer);
153
154 // If there are no more subscribers then remove the list.
155 if (subscribers.isEmpty()) {
156 mLayerSubscriptions.remove(layer);
157 }
158 }
159 }
160
161 /**
162 * Remove a subscriber subscription to all data messages.
163 *
164 * @param subscriber a VMS subscriber.
165 */
166 public void removeSubscription(IVmsSubscriberClient subscriber) {
167 synchronized (mLock) {
168 ++mSequenceNumber;
169 mPromiscuousSubscribers.remove(subscriber);
170 VmsOperationRecorder.get().removePromiscuousSubscription(mSequenceNumber);
171 }
172 }
173
174 /**
175 * Remove a subscription to data messages from a VMS layer from a specific publisher.
176 *
177 * @param subscriber a VMS subscriber.
178 * @param layer the layer to unsubscribing from.
179 * @param publisherId the publisher ID.
180 */
181 public void removeSubscription(IVmsSubscriberClient subscriber,
182 VmsLayer layer,
183 int publisherId) {
184 synchronized (mLock) {
185 ++mSequenceNumber;
186
187 Map<Integer, Set<IVmsSubscriberClient>> subscribersToPublishers =
188 mLayerSubscriptionsToPublishers.get(layer);
189
190 if (subscribersToPublishers == null) {
191 return;
192 }
193
194 Set<IVmsSubscriberClient> subscribers = subscribersToPublishers.get(publisherId);
195
196 if (subscribers == null) {
197 return;
198 }
199 subscribers.remove(subscriber);
200
201 if (subscribers.isEmpty()) {
202 subscribersToPublishers.remove(publisherId);
203 }
204
205 if (subscribersToPublishers.isEmpty()) {
206 mLayerSubscriptionsToPublishers.remove(layer);
207 }
208 }
209 }
210
211 /**
212 * Remove a subscriber from all routes (optional operation).
213 *
214 * @param subscriber a VMS subscriber.
215 */
216 public void removeDeadSubscriber(IVmsSubscriberClient subscriber) {
217 synchronized (mLock) {
218 // Remove the subscriber from all the routes.
219 for (VmsLayer layer : mLayerSubscriptions.keySet()) {
220 removeSubscription(subscriber, layer);
221 }
222 // Remove the subscriber from the loggers.
223 removeSubscription(subscriber);
224 }
225 }
226
227 /**
228 * Returns a list of all the subscribers for a layer from a publisher. This includes
229 * subscribers that subscribed to this layer from all publishers, subscribed to this layer
230 * from a specific publisher, and the promiscuous subscribers.
231 *
232 * @param layer The layer of the message.
233 * @param publisherId the ID of the client that published the message to be routed.
234 * @return a list of the subscribers.
235 */
236 public Set<IVmsSubscriberClient> getSubscribersForLayerFromPublisher(VmsLayer layer,
237 int publisherId) {
238 Set<IVmsSubscriberClient> subscribers = new HashSet<>();
239 synchronized (mLock) {
240 // Add the subscribers which explicitly subscribed to this layer
241 if (mLayerSubscriptions.containsKey(layer)) {
242 subscribers.addAll(mLayerSubscriptions.get(layer));
243 }
244
245 // Add the subscribers which explicitly subscribed to this layer and publisher
246 if (mLayerSubscriptionsToPublishers.containsKey(layer)) {
247 if (mLayerSubscriptionsToPublishers.get(layer).containsKey(publisherId)) {
248 subscribers.addAll(mLayerSubscriptionsToPublishers.get(layer).get(publisherId));
249 }
250 }
251
252 // Add the promiscuous subscribers.
253 subscribers.addAll(mPromiscuousSubscribers);
254 }
255 return subscribers;
256 }
257
258 /**
259 * Returns a list with all the subscribers.
260 */
261 public Set<IVmsSubscriberClient> getAllSubscribers() {
262 Set<IVmsSubscriberClient> subscribers = new HashSet<>();
263 synchronized (mLock) {
264 for (VmsLayer layer : mLayerSubscriptions.keySet()) {
265 subscribers.addAll(mLayerSubscriptions.get(layer));
266 }
267 // Add the promiscuous subscribers.
268 subscribers.addAll(mPromiscuousSubscribers);
269 }
270 return subscribers;
271 }
272
273 /**
274 * Checks if a subscriber is subscribed to any messages.
275 *
276 * @param subscriber that may have subscription.
277 * @return true if the subscriber uis subscribed to messages.
278 */
279 public boolean containsSubscriber(IVmsSubscriberClient subscriber) {
280 synchronized (mLock) {
281 // Check if subscriber is subscribed to a layer.
282 for (Set<IVmsSubscriberClient> layerSubscribers : mLayerSubscriptions.values()) {
283 if (layerSubscribers.contains(subscriber)) {
284 return true;
285 }
286 }
287 // Check is subscriber is subscribed to all data messages.
288 return mPromiscuousSubscribers.contains(subscriber);
289 }
290 }
291
292 /**
293 * Add a layer and version to the HAL subscriptions.
294 *
295 * @param layer the HAL subscribes to.
296 */
297 public void addHalSubscription(VmsLayer layer) {
298 synchronized (mLock) {
299 ++mSequenceNumber;
300 mHalSubscriptions.add(layer);
301 VmsOperationRecorder.get().addHalSubscription(mSequenceNumber, layer);
302 }
303 }
304
305 public void addHalSubscriptionToPublisher(VmsLayer layer, int publisherId) {
306 synchronized (mLock) {
307 ++mSequenceNumber;
308
309 Set<Integer> publisherIdsForLayer = mHalSubscriptionsToPublishers.get(layer);
310 if (publisherIdsForLayer == null) {
311 publisherIdsForLayer = new HashSet<>();
312 mHalSubscriptionsToPublishers.put(layer, publisherIdsForLayer);
313 }
314 publisherIdsForLayer.add(publisherId);
315 }
316 }
317
318 /**
319 * remove a layer and version to the HAL subscriptions.
320 *
321 * @param layer the HAL unsubscribes from.
322 */
323 public void removeHalSubscription(VmsLayer layer) {
324 synchronized (mLock) {
325 ++mSequenceNumber;
326 mHalSubscriptions.remove(layer);
327 VmsOperationRecorder.get().removeHalSubscription(mSequenceNumber, layer);
328 }
329 }
330
331 public void removeHalSubscriptionToPublisher(VmsLayer layer, int publisherId) {
332 synchronized (mLock) {
333 ++mSequenceNumber;
334
335 Set<Integer> publisherIdsForLayer = mHalSubscriptionsToPublishers.get(layer);
336 if (publisherIdsForLayer == null) {
337 return;
338 }
339 publisherIdsForLayer.remove(publisherId);
340
341 if (publisherIdsForLayer.isEmpty()) {
342 mHalSubscriptionsToPublishers.remove(layer);
343 }
344 }
345 }
346
347 /**
348 * checks if the HAL is subscribed to a layer.
349 *
350 * @param layer
351 * @return true if the HAL is subscribed to layer.
352 */
353 public boolean isHalSubscribed(VmsLayer layer) {
354 synchronized (mLock) {
355 return mHalSubscriptions.contains(layer);
356 }
357 }
358
359 /**
360 * checks if there are subscribers to a layer.
361 *
362 * @param layer
363 * @return true if there are subscribers to layer.
364 */
365 public boolean hasLayerSubscriptions(VmsLayer layer) {
366 synchronized (mLock) {
367 return mLayerSubscriptions.containsKey(layer) || mHalSubscriptions.contains(layer);
368 }
369 }
370
371 /**
372 * returns true if there is already a subscription for the layer from publisherId.
373 *
374 * @param layer
375 * @param publisherId
376 * @return
377 */
378 public boolean hasLayerFromPublisherSubscriptions(VmsLayer layer, int publisherId) {
379 synchronized (mLock) {
380 boolean hasClientSubscription =
381 mLayerSubscriptionsToPublishers.containsKey(layer) &&
382 mLayerSubscriptionsToPublishers.get(layer).containsKey(publisherId);
383
384 boolean hasHalSubscription = mHalSubscriptionsToPublishers.containsKey(layer) &&
385 mHalSubscriptionsToPublishers.get(layer).contains(publisherId);
386
387 return hasClientSubscription || hasHalSubscription;
388 }
389 }
390
391 /**
392 * @return a Set of layers and versions which VMS clients are subscribed to.
393 */
394 public VmsSubscriptionState getSubscriptionState() {
395 synchronized (mLock) {
396 Set<VmsLayer> layers = new HashSet<>();
397 layers.addAll(mLayerSubscriptions.keySet());
398 layers.addAll(mHalSubscriptions);
399
400
401 Set<VmsAssociatedLayer> layersFromPublishers = new HashSet<>();
402 layersFromPublishers.addAll(mLayerSubscriptionsToPublishers.entrySet()
403 .stream()
404 .map(e -> new VmsAssociatedLayer(e.getKey(), e.getValue().keySet()))
405 .collect(Collectors.toSet()));
406 layersFromPublishers.addAll(mHalSubscriptionsToPublishers.entrySet()
407 .stream()
408 .map(e -> new VmsAssociatedLayer(e.getKey(), e.getValue()))
409 .collect(Collectors.toSet()));
410
411 return new VmsSubscriptionState(mSequenceNumber, layers, layersFromPublishers);
412 }
413 }
414} \ No newline at end of file
diff --git a/service/src/com/android/car/VmsSubscriberService.java b/service/src/com/android/car/VmsSubscriberService.java
deleted file mode 100644
index 94f08445..00000000
--- a/service/src/com/android/car/VmsSubscriberService.java
+++ /dev/null
@@ -1,353 +0,0 @@
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
17package com.android.car;
18
19import android.car.Car;
20import android.car.annotation.FutureFeature;
21import android.car.vms.IVmsSubscriberClient;
22import android.car.vms.IVmsSubscriberService;
23import android.car.vms.VmsAssociatedLayer;
24import android.car.vms.VmsLayer;
25import android.content.Context;
26import android.os.IBinder;
27import android.os.RemoteException;
28import android.util.Log;
29
30import com.android.car.hal.VmsHalService;
31import com.android.internal.annotations.GuardedBy;
32
33import java.io.PrintWriter;
34import java.util.ArrayList;
35import java.util.Collections;
36import java.util.HashMap;
37import java.util.HashSet;
38import java.util.List;
39import java.util.Map;
40import java.util.Set;
41
42/**
43 * + Receives HAL updates by implementing VmsHalService.VmsHalListener.
44 * + Offers subscriber/publisher services by implementing IVmsService.Stub.
45 */
46@FutureFeature
47public class VmsSubscriberService extends IVmsSubscriberService.Stub
48 implements CarServiceBase, VmsHalService.VmsHalSubscriberListener {
49 private static final boolean DBG = true;
50 private static final String PERMISSION = Car.PERMISSION_VMS_SUBSCRIBER;
51 private static final String TAG = "VmsSubscriberService";
52
53 private final Context mContext;
54 private final VmsHalService mHal;
55
56 @GuardedBy("mSubscriberServiceLock")
57 private final VmsSubscribersManager mSubscribersManager = new VmsSubscribersManager();
58 private final Object mSubscriberServiceLock = new Object();
59
60 /**
61 * Keeps track of subscribers of this service.
62 */
63 class VmsSubscribersManager {
64 /**
65 * Allows to modify mSubscriberMap and mListenerDeathRecipientMap as a single unit.
66 */
67 private final Object mListenerManagerLock = new Object();
68 @GuardedBy("mListenerManagerLock")
69 private final Map<IBinder, ListenerDeathRecipient> mListenerDeathRecipientMap =
70 new HashMap<>();
71 @GuardedBy("mListenerManagerLock")
72 private final Map<IBinder, IVmsSubscriberClient> mSubscriberMap = new HashMap<>();
73
74 class ListenerDeathRecipient implements IBinder.DeathRecipient {
75 private IBinder mSubscriberBinder;
76
77 ListenerDeathRecipient(IBinder subscriberBinder) {
78 mSubscriberBinder = subscriberBinder;
79 }
80
81 /**
82 * Listener died. Remove it from this service.
83 */
84 @Override
85 public void binderDied() {
86 if (DBG) {
87 Log.d(TAG, "binderDied " + mSubscriberBinder);
88 }
89
90 // Get the Listener from the Binder
91 IVmsSubscriberClient subscriber = mSubscriberMap.get(mSubscriberBinder);
92
93 // Remove the subscriber subscriptions.
94 if (subscriber != null) {
95 Log.d(TAG, "Removing subscriptions for dead subscriber: " + subscriber);
96 mHal.removeDeadSubscriber(subscriber);
97 } else {
98 Log.d(TAG, "Handling dead binder with no matching subscriber");
99
100 }
101
102 // Remove binder
103 VmsSubscribersManager.this.removeListener(mSubscriberBinder);
104 }
105
106 void release() {
107 mSubscriberBinder.unlinkToDeath(this, 0);
108 }
109 }
110
111 public void release() {
112 for (ListenerDeathRecipient recipient : mListenerDeathRecipientMap.values()) {
113 recipient.release();
114 }
115 mListenerDeathRecipientMap.clear();
116 mSubscriberMap.clear();
117 }
118
119 /**
120 * Adds the subscriber and a death recipient associated to it.
121 *
122 * @param subscriber to be added.
123 * @throws IllegalArgumentException if the subscriber is null.
124 * @throws IllegalStateException if it was not possible to link a death recipient to the
125 * subscriber.
126 */
127 public void add(IVmsSubscriberClient subscriber) {
128 ICarImpl.assertPermission(mContext, PERMISSION);
129 if (subscriber == null) {
130 Log.e(TAG, "register: subscriber is null.");
131 throw new IllegalArgumentException("subscriber cannot be null.");
132 }
133 if (DBG) {
134 Log.d(TAG, "register: " + subscriber);
135 }
136 IBinder subscriberBinder = subscriber.asBinder();
137 synchronized (mListenerManagerLock) {
138 if (mSubscriberMap.containsKey(subscriberBinder)) {
139 // Already registered, nothing to do.
140 return;
141 }
142 ListenerDeathRecipient deathRecipient =
143 new ListenerDeathRecipient(subscriberBinder);
144 try {
145 subscriberBinder.linkToDeath(deathRecipient, 0);
146 } catch (RemoteException e) {
147 Log.e(TAG, "Failed to link death for recipient. ", e);
148 throw new IllegalStateException(Car.CAR_NOT_CONNECTED_EXCEPTION_MSG);
149 }
150 mListenerDeathRecipientMap.put(subscriberBinder, deathRecipient);
151 mSubscriberMap.put(subscriberBinder, subscriber);
152 }
153 }
154
155 /**
156 * Removes the subscriber and associated death recipient.
157 *
158 * @param subscriber to be removed.
159 * @throws IllegalArgumentException if subscriber is null.
160 */
161 public void remove(IVmsSubscriberClient subscriber) {
162 if (DBG) {
163 Log.d(TAG, "unregisterListener");
164 }
165 ICarImpl.assertPermission(mContext, PERMISSION);
166 if (subscriber == null) {
167 Log.e(TAG, "unregister: subscriber is null.");
168 throw new IllegalArgumentException("Listener is null");
169 }
170 IBinder subscriberBinder = subscriber.asBinder();
171 removeListener(subscriberBinder);
172 }
173
174 // Removes the subscriberBinder from the current state.
175 // The function assumes that binder will exist both in subscriber and death recipients list.
176 private void removeListener(IBinder subscriberBinder) {
177 synchronized (mListenerManagerLock) {
178 boolean found = mSubscriberMap.remove(subscriberBinder) != null;
179 if (found) {
180 mListenerDeathRecipientMap.get(subscriberBinder).release();
181 mListenerDeathRecipientMap.remove(subscriberBinder);
182 } else {
183 Log.e(TAG, "removeListener: subscriber was not previously registered.");
184 }
185 }
186 }
187
188 /**
189 * Returns list of subscribers currently registered.
190 *
191 * @return list of subscribers.
192 */
193 public List<IVmsSubscriberClient> getListeners() {
194 synchronized (mListenerManagerLock) {
195 return new ArrayList<>(mSubscriberMap.values());
196 }
197 }
198 }
199
200 public VmsSubscriberService(Context context, VmsHalService hal) {
201 mContext = context;
202 mHal = hal;
203 }
204
205 // Implements CarServiceBase interface.
206 @Override
207 public void init() {
208 mHal.addSubscriberListener(this);
209 }
210
211 @Override
212 public void release() {
213 mSubscribersManager.release();
214 mHal.removeSubscriberListener(this);
215 }
216
217 @Override
218 public void dump(PrintWriter writer) {
219 }
220
221 // Implements IVmsService interface.
222 @Override
223 public void addVmsSubscriberToNotifications(IVmsSubscriberClient subscriber) {
224 synchronized (mSubscriberServiceLock) {
225 // Add the subscriber so it can subscribe.
226 mSubscribersManager.add(subscriber);
227 }
228 }
229
230 @Override
231 public void removeVmsSubscriberToNotifications(IVmsSubscriberClient subscriber) {
232 synchronized (mSubscriberServiceLock) {
233 if (mHal.containsSubscriber(subscriber)) {
234 throw new IllegalArgumentException("Subscriber has active subscriptions.");
235 }
236 mSubscribersManager.remove(subscriber);
237 }
238 }
239
240 @Override
241 public void addVmsSubscriber(IVmsSubscriberClient subscriber, VmsLayer layer) {
242 synchronized (mSubscriberServiceLock) {
243 // Add the subscriber so it can subscribe.
244 mSubscribersManager.add(subscriber);
245
246 // Add the subscription for the layer.
247 mHal.addSubscription(subscriber, layer);
248 }
249 }
250
251 @Override
252 public void removeVmsSubscriber(IVmsSubscriberClient subscriber, VmsLayer layer) {
253 synchronized (mSubscriberServiceLock) {
254 // Remove the subscription.
255 mHal.removeSubscription(subscriber, layer);
256 }
257 }
258
259 @Override
260 public void addVmsSubscriberToPublisher(IVmsSubscriberClient subscriber,
261 VmsLayer layer,
262 int publisherId) {
263 synchronized (mSubscriberServiceLock) {
264 // Add the subscriber so it can subscribe.
265 mSubscribersManager.add(subscriber);
266
267 // Add the subscription for the layer.
268 mHal.addSubscription(subscriber, layer, publisherId);
269 }
270 }
271
272 @Override
273 public void removeVmsSubscriberToPublisher(IVmsSubscriberClient subscriber,
274 VmsLayer layer,
275 int publisherId) {
276 synchronized (mSubscriberServiceLock) {
277 // Remove the subscription.
278 mHal.removeSubscription(subscriber, layer, publisherId);
279 }
280 }
281
282 @Override
283 public void addVmsSubscriberPassive(IVmsSubscriberClient subscriber) {
284 synchronized (mSubscriberServiceLock) {
285 mSubscribersManager.add(subscriber);
286 mHal.addSubscription(subscriber);
287 }
288 }
289
290 @Override
291 public void removeVmsSubscriberPassive(IVmsSubscriberClient subscriber) {
292 synchronized (mSubscriberServiceLock) {
293 // Remove the subscription.
294 mHal.removeSubscription(subscriber);
295 }
296 }
297
298 @Override
299 public byte[] getPublisherInfo(int publisherId) {
300 synchronized (mSubscriberServiceLock) {
301 return mHal.getPublisherInfo(publisherId);
302 }
303 }
304
305 @Override
306 public List<VmsLayer> getAvailableLayers() {
307 //TODO(asafro): return the list of available layers once logic is implemented.
308 return Collections.emptyList();
309 }
310
311 // Implements VmsHalSubscriberListener interface
312 @Override
313 public void onDataMessage(VmsLayer layer, int publisherId, byte[] payload) {
314 if (DBG) {
315 Log.d(TAG, "Publishing a message for layer: " + layer);
316 }
317
318 Set<IVmsSubscriberClient> subscribers =
319 mHal.getSubscribersForLayerFromPublisher(layer, publisherId);
320
321 for (IVmsSubscriberClient subscriber : subscribers) {
322 try {
323 subscriber.onVmsMessageReceived(layer, payload);
324 } catch (RemoteException e) {
325 // If we could not send a record, its likely the connection snapped. Let the binder
326 // death handle the situation.
327 Log.e(TAG, "onVmsMessageReceived calling failed: ", e);
328 }
329 }
330 }
331
332 @Override
333 public void onLayersAvaiabilityChange(List<VmsAssociatedLayer> availableLayers) {
334 if (DBG) {
335 Log.d(TAG, "Publishing layers availability change: " + availableLayers);
336 }
337
338 Set<IVmsSubscriberClient> subscribers;
339 synchronized (mSubscriberServiceLock) {
340 subscribers = new HashSet<>(mSubscribersManager.getListeners());
341 }
342
343 for (IVmsSubscriberClient subscriber : subscribers) {
344 try {
345 subscriber.onLayersAvailabilityChanged(availableLayers);
346 } catch (RemoteException e) {
347 // If we could not send a record, its likely the connection snapped. Let the binder
348 // death handle the situation.
349 Log.e(TAG, "onLayersAvailabilityChanged calling failed: ", e);
350 }
351 }
352 }
353}
diff --git a/service/src/com/android/car/hal/VehicleHal.java b/service/src/com/android/car/hal/VehicleHal.java
index 21f8f511..44c81d7f 100644
--- a/service/src/com/android/car/hal/VehicleHal.java
+++ b/service/src/com/android/car/hal/VehicleHal.java
@@ -80,8 +80,6 @@ public class VehicleHal extends IVehicleCallback.Stub {
80 private final VendorExtensionHalService mVendorExtensionHal; 80 private final VendorExtensionHalService mVendorExtensionHal;
81 private DiagnosticHalService mDiagnosticHal = null; 81 private DiagnosticHalService mDiagnosticHal = null;
82 82
83 @FutureFeature
84 private VmsHalService mVmsHal;
85 83
86 84
87 /** Might be re-assigned if Vehicle HAL is reconnected. */ 85 /** Might be re-assigned if Vehicle HAL is reconnected. */
@@ -108,9 +106,6 @@ public class VehicleHal extends IVehicleCallback.Stub {
108 mHvacHal = new HvacHalService(this); 106 mHvacHal = new HvacHalService(this);
109 mInputHal = new InputHalService(this); 107 mInputHal = new InputHalService(this);
110 mVendorExtensionHal = new VendorExtensionHalService(this); 108 mVendorExtensionHal = new VendorExtensionHalService(this);
111 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
112 mVmsHal = new VmsHalService(this);
113 }
114 mDiagnosticHal = new DiagnosticHalService(this); 109 mDiagnosticHal = new DiagnosticHalService(this);
115 mAllServices.addAll(Arrays.asList(mPowerHal, 110 mAllServices.addAll(Arrays.asList(mPowerHal,
116 mSensorHal, 111 mSensorHal,
@@ -122,9 +117,6 @@ public class VehicleHal extends IVehicleCallback.Stub {
122 mInputHal, 117 mInputHal,
123 mVendorExtensionHal, 118 mVendorExtensionHal,
124 mDiagnosticHal)); 119 mDiagnosticHal));
125 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
126 mAllServices.add(mVmsHal);
127 }
128 120
129 mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/); 121 mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/);
130 } 122 }
@@ -146,10 +138,6 @@ public class VehicleHal extends IVehicleCallback.Stub {
146 mVendorExtensionHal = null; 138 mVendorExtensionHal = null;
147 mDiagnosticHal = null; 139 mDiagnosticHal = null;
148 140
149 if (FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
150 mVmsHal = null;
151 }
152
153 mHalClient = halClient; 141 mHalClient = halClient;
154 } 142 }
155 143
@@ -169,7 +157,6 @@ public class VehicleHal extends IVehicleCallback.Stub {
169 mHvacHal = hvacHal; 157 mHvacHal = hvacHal;
170 mInputHal = null; 158 mInputHal = null;
171 mVendorExtensionHal = null; 159 mVendorExtensionHal = null;
172 mVmsHal = null;
173 mHalClient = halClient; 160 mHalClient = halClient;
174 mDiagnosticHal = diagnosticHal; 161 mDiagnosticHal = diagnosticHal;
175 } 162 }
@@ -281,9 +268,6 @@ public class VehicleHal extends IVehicleCallback.Stub {
281 return mVendorExtensionHal; 268 return mVendorExtensionHal;
282 } 269 }
283 270
284 @FutureFeature
285 public VmsHalService getVmsHal() { return mVmsHal; }
286
287 private void assertServiceOwnerLocked(HalServiceBase service, int property) { 271 private void assertServiceOwnerLocked(HalServiceBase service, int property) {
288 if (service != mPropertyHandlers.get(property)) { 272 if (service != mPropertyHandlers.get(property)) {
289 throw new IllegalArgumentException("Property 0x" + toHexString(property) 273 throw new IllegalArgumentException("Property 0x" + toHexString(property)
diff --git a/service/src/com/android/car/hal/VmsHalService.java b/service/src/com/android/car/hal/VmsHalService.java
deleted file mode 100644
index d20a453f..00000000
--- a/service/src/com/android/car/hal/VmsHalService.java
+++ /dev/null
@@ -1,850 +0,0 @@
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 */
16package com.android.car.hal;
17
18import static com.android.car.CarServiceUtils.toByteArray;
19import static java.lang.Integer.toHexString;
20
21import android.car.VehicleAreaType;
22import android.car.annotation.FutureFeature;
23import android.car.vms.IVmsSubscriberClient;
24import android.car.vms.VmsLayer;
25import android.car.vms.VmsAssociatedLayer;
26import android.car.vms.VmsLayerDependency;
27import android.car.vms.VmsLayersOffering;
28import android.car.vms.VmsOperationRecorder;
29import android.car.vms.VmsSubscriptionState;
30import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
31import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
32import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
33import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
34import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
35import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerAndPublisherIdIntegerValuesIndex;
36import android.hardware.automotive.vehicle.V2_0.VmsOfferingMessageIntegerValuesIndex;
37import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
38import android.os.Binder;
39import android.os.IBinder;
40import android.util.Log;
41import com.android.car.CarLog;
42import com.android.car.VmsLayersAvailability;
43import com.android.car.VmsPublishersInfo;
44import com.android.car.VmsRouting;
45import com.android.internal.annotations.GuardedBy;
46
47import java.io.PrintWriter;
48import java.util.Arrays;
49import java.util.ArrayList;
50import java.util.Collection;
51import java.util.Collections;
52import java.util.HashMap;
53import java.util.HashSet;
54import java.util.LinkedList;
55import java.util.List;
56import java.util.Map;
57import java.util.Set;
58import java.util.concurrent.CopyOnWriteArrayList;
59
60/**
61 * This is a glue layer between the VehicleHal and the VmsService. It sends VMS properties back and
62 * forth.
63 */
64@FutureFeature
65public class VmsHalService extends HalServiceBase {
66
67 private static final boolean DBG = true;
68 private static final int HAL_PROPERTY_ID = VehicleProperty.VEHICLE_MAP_SERVICE;
69 private static final String TAG = "VmsHalService";
70
71 private final static List<Integer> AVAILABILITY_MESSAGE_TYPES = Collections.unmodifiableList(
72 Arrays.asList(
73 VmsMessageType.AVAILABILITY_RESPONSE,
74 VmsMessageType.AVAILABILITY_CHANGE));
75
76 private boolean mIsSupported = false;
77 private CopyOnWriteArrayList<VmsHalPublisherListener> mPublisherListeners =
78 new CopyOnWriteArrayList<>();
79 private CopyOnWriteArrayList<VmsHalSubscriberListener> mSubscriberListeners =
80 new CopyOnWriteArrayList<>();
81
82 private final IBinder mHalPublisherToken = new Binder();
83 private final VehicleHal mVehicleHal;
84
85 private final Object mLock = new Object();
86 private final VmsRouting mRouting = new VmsRouting();
87 @GuardedBy("mLock")
88 private final Map<IBinder, VmsLayersOffering> mOfferings = new HashMap<>();
89 @GuardedBy("mLock")
90 private final VmsLayersAvailability mAvailableLayers = new VmsLayersAvailability();
91 private final VmsPublishersInfo mPublishersInfo = new VmsPublishersInfo();
92
93 /**
94 * The VmsPublisherService implements this interface to receive data from the HAL.
95 */
96 public interface VmsHalPublisherListener {
97 void onChange(VmsSubscriptionState subscriptionState);
98 }
99
100 /**
101 * The VmsSubscriberService implements this interface to receive data from the HAL.
102 */
103 public interface VmsHalSubscriberListener {
104 // Notifies the listener on a data Message from a publisher.
105 void onDataMessage(VmsLayer layer, int publisherId, byte[] payload);
106
107 // Notifies the listener on a change in available layers.
108 void onLayersAvaiabilityChange(List<VmsAssociatedLayer> availableLayers);
109 }
110
111 /**
112 * The VmsService implements this interface to receive data from the HAL.
113 */
114 protected VmsHalService(VehicleHal vehicleHal) {
115 mVehicleHal = vehicleHal;
116 if (DBG) {
117 Log.d(TAG, "started VmsHalService!");
118 }
119 }
120
121 public void addPublisherListener(VmsHalPublisherListener listener) {
122 mPublisherListeners.add(listener);
123 }
124
125 public void addSubscriberListener(VmsHalSubscriberListener listener) {
126 mSubscriberListeners.add(listener);
127 }
128
129 public void removePublisherListener(VmsHalPublisherListener listener) {
130 mPublisherListeners.remove(listener);
131 }
132
133 public void removeSubscriberListener(VmsHalSubscriberListener listener) {
134 mSubscriberListeners.remove(listener);
135 }
136
137 public void addSubscription(IVmsSubscriberClient listener, VmsLayer layer) {
138 boolean firstSubscriptionForLayer = false;
139 synchronized (mLock) {
140 // Check if publishers need to be notified about this change in subscriptions.
141 firstSubscriptionForLayer = !mRouting.hasLayerSubscriptions(layer);
142
143 // Add the listeners subscription to the layer
144 mRouting.addSubscription(listener, layer);
145 }
146 if (firstSubscriptionForLayer) {
147 notifyHalPublishers(layer, true);
148 notifyClientPublishers();
149 }
150 }
151
152 public void removeSubscription(IVmsSubscriberClient listener, VmsLayer layer) {
153 boolean layerHasSubscribers = true;
154 synchronized (mLock) {
155 if (!mRouting.hasLayerSubscriptions(layer)) {
156 Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
157 return;
158 }
159
160 // Remove the listeners subscription to the layer
161 mRouting.removeSubscription(listener, layer);
162
163 // Check if publishers need to be notified about this change in subscriptions.
164 layerHasSubscribers = mRouting.hasLayerSubscriptions(layer);
165 }
166 if (!layerHasSubscribers) {
167 notifyHalPublishers(layer, false);
168 notifyClientPublishers();
169 }
170 }
171
172 public void addSubscription(IVmsSubscriberClient listener) {
173 synchronized (mLock) {
174 mRouting.addSubscription(listener);
175 }
176 }
177
178 public void removeSubscription(IVmsSubscriberClient listener) {
179 synchronized (mLock) {
180 mRouting.removeSubscription(listener);
181 }
182 }
183
184 public void addSubscription(IVmsSubscriberClient listener, VmsLayer layer, int publisherId) {
185 boolean firstSubscriptionForLayer = false;
186 synchronized (mLock) {
187 // Check if publishers need to be notified about this change in subscriptions.
188 firstSubscriptionForLayer = !(mRouting.hasLayerSubscriptions(layer) ||
189 mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId));
190
191 // Add the listeners subscription to the layer
192 mRouting.addSubscription(listener, layer, publisherId);
193 }
194 if (firstSubscriptionForLayer) {
195 notifyHalPublishers(layer, true);
196 notifyClientPublishers();
197 }
198 }
199
200 public void removeSubscription(IVmsSubscriberClient listener, VmsLayer layer, int publisherId) {
201 boolean layerHasSubscribers = true;
202 synchronized (mLock) {
203 if (!mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId)) {
204 Log.i(TAG, "Trying to remove a layer with no subscription: " +
205 layer + ", publisher ID:" + publisherId);
206 return;
207 }
208
209 // Remove the listeners subscription to the layer
210 mRouting.removeSubscription(listener, layer, publisherId);
211
212 // Check if publishers need to be notified about this change in subscriptions.
213 layerHasSubscribers = mRouting.hasLayerSubscriptions(layer) ||
214 mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId);
215 }
216 if (!layerHasSubscribers) {
217 notifyHalPublishers(layer, false);
218 notifyClientPublishers();
219 }
220 }
221
222 public void removeDeadSubscriber(IVmsSubscriberClient listener) {
223 synchronized (mLock) {
224 mRouting.removeDeadSubscriber(listener);
225 }
226 }
227
228 public Set<IVmsSubscriberClient> getSubscribersForLayerFromPublisher(VmsLayer layer,
229 int publisherId) {
230 synchronized (mLock) {
231 return mRouting.getSubscribersForLayerFromPublisher(layer, publisherId);
232 }
233 }
234
235 public Set<IVmsSubscriberClient> getAllSubscribers() {
236 synchronized (mLock) {
237 return mRouting.getAllSubscribers();
238 }
239 }
240
241 public boolean isHalSubscribed(VmsLayer layer) {
242 synchronized (mLock) {
243 return mRouting.isHalSubscribed(layer);
244 }
245 }
246
247 public VmsSubscriptionState getSubscriptionState() {
248 synchronized (mLock) {
249 return mRouting.getSubscriptionState();
250 }
251 }
252
253 /**
254 * Assigns an idempotent ID for publisherInfo and stores it. The idempotency in this case means
255 * that the same publisherInfo will always, within a trip of the vehicle, return the same ID.
256 * The publisherInfo should be static for a binary and should only change as part of a software
257 * update. The publisherInfo is a serialized proto message which VMS clients can interpret.
258 */
259 public int getPublisherId(byte[] publisherInfo) {
260 if (DBG) {
261 Log.i(TAG, "Getting publisher static ID");
262 }
263 synchronized (mLock) {
264 return mPublishersInfo.getIdForInfo(publisherInfo);
265 }
266 }
267
268 public byte[] getPublisherInfo(int publisherId) {
269 if (DBG) {
270 Log.i(TAG, "Getting information for publisher ID: " + publisherId);
271 }
272 synchronized (mLock) {
273 return mPublishersInfo.getPublisherInfo(publisherId);
274 }
275 }
276
277 private void addHalSubscription(VmsLayer layer) {
278 boolean firstSubscriptionForLayer = true;
279 synchronized (mLock) {
280 // Check if publishers need to be notified about this change in subscriptions.
281 firstSubscriptionForLayer = !mRouting.hasLayerSubscriptions(layer);
282
283 // Add the listeners subscription to the layer
284 mRouting.addHalSubscription(layer);
285 }
286 if (firstSubscriptionForLayer) {
287 notifyHalPublishers(layer, true);
288 notifyClientPublishers();
289 }
290 }
291
292 private void addHalSubscriptionToPublisher(VmsLayer layer, int publisherId) {
293 boolean firstSubscriptionForLayer = true;
294 synchronized (mLock) {
295 // Check if publishers need to be notified about this change in subscriptions.
296 firstSubscriptionForLayer = !(mRouting.hasLayerSubscriptions(layer) ||
297 mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId));
298
299 // Add the listeners subscription to the layer
300 mRouting.addHalSubscriptionToPublisher(layer, publisherId);
301 }
302 if (firstSubscriptionForLayer) {
303 notifyHalPublishers(layer, publisherId, true);
304 notifyClientPublishers();
305 }
306 }
307
308 private void removeHalSubscription(VmsLayer layer) {
309 boolean layerHasSubscribers = true;
310 synchronized (mLock) {
311 if (!mRouting.hasLayerSubscriptions(layer)) {
312 Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
313 return;
314 }
315
316 // Remove the listeners subscription to the layer
317 mRouting.removeHalSubscription(layer);
318
319 // Check if publishers need to be notified about this change in subscriptions.
320 layerHasSubscribers = mRouting.hasLayerSubscriptions(layer);
321 }
322 if (!layerHasSubscribers) {
323 notifyHalPublishers(layer, false);
324 notifyClientPublishers();
325 }
326 }
327
328 public void removeHalSubscriptionFromPublisher(VmsLayer layer, int publisherId) {
329 boolean layerHasSubscribers = true;
330 synchronized (mLock) {
331 if (!mRouting.hasLayerSubscriptions(layer)) {
332 Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
333 return;
334 }
335
336 // Remove the listeners subscription to the layer
337 mRouting.removeHalSubscriptionToPublisher(layer, publisherId);
338
339 // Check if publishers need to be notified about this change in subscriptions.
340 layerHasSubscribers = mRouting.hasLayerSubscriptions(layer) ||
341 mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId);
342 }
343 if (!layerHasSubscribers) {
344 notifyHalPublishers(layer, publisherId, false);
345 notifyClientPublishers();
346 }
347 }
348
349 public boolean containsSubscriber(IVmsSubscriberClient subscriber) {
350 synchronized (mLock) {
351 return mRouting.containsSubscriber(subscriber);
352 }
353 }
354
355 public void setPublisherLayersOffering(IBinder publisherToken, VmsLayersOffering offering) {
356 Set<VmsAssociatedLayer> availableLayers = Collections.EMPTY_SET;
357 synchronized (mLock) {
358 updateOffering(publisherToken, offering);
359 VmsOperationRecorder.get().setPublisherLayersOffering(offering);
360 availableLayers = mAvailableLayers.getAvailableLayers();
361 }
362 notifyOfAvailabilityChange(availableLayers);
363 }
364
365 public Set<VmsAssociatedLayer> getAvailableLayers() {
366 //TODO(b/36872877): wrap available layers in VmsAvailabilityState similar to VmsSubscriptionState.
367 synchronized (mLock) {
368 return mAvailableLayers.getAvailableLayers();
369 }
370 }
371
372 /**
373 * Notify all the publishers and the HAL on subscription changes regardless of who triggered
374 * the change.
375 *
376 * @param layer layer which is being subscribed to or unsubscribed from.
377 * @param hasSubscribers indicates if the notification is for subscription or unsubscription.
378 */
379 private void notifyHalPublishers(VmsLayer layer, boolean hasSubscribers) {
380 // notify the HAL
381 setSubscriptionRequest(layer, hasSubscribers);
382 }
383
384 private void notifyHalPublishers(VmsLayer layer, int publisherId, boolean hasSubscribers) {
385 // notify the HAL
386 setSubscriptionToPublisherRequest(layer, publisherId, hasSubscribers);
387 }
388
389 private void notifyClientPublishers() {
390 // Notify the App publishers
391 for (VmsHalPublisherListener listener : mPublisherListeners) {
392 // Besides the list of layers, also a timestamp is provided to the clients.
393 // They should ignore any notification with a timestamp that is older than the most
394 // recent timestamp they have seen.
395 listener.onChange(getSubscriptionState());
396 }
397 }
398
399 /**
400 * Notify all the subscribers and the HAL on layers availability change.
401 *
402 * @param availableLayers the layers which publishers claim they made publish.
403 */
404 private void notifyOfAvailabilityChange(Set<VmsAssociatedLayer> availableLayers) {
405 // notify the HAL
406 notifyAvailabilityChangeToHal(availableLayers);
407
408 // Notify the App subscribers
409 for (VmsHalSubscriberListener listener : mSubscriberListeners) {
410 listener.onLayersAvaiabilityChange(new ArrayList<>(availableLayers));
411 }
412 }
413
414 @Override
415 public void init() {
416 if (DBG) {
417 Log.d(TAG, "init()");
418 }
419 if (mIsSupported) {
420 mVehicleHal.subscribeProperty(this, HAL_PROPERTY_ID);
421 }
422 }
423
424 @Override
425 public void release() {
426 if (DBG) {
427 Log.d(TAG, "release()");
428 }
429 if (mIsSupported) {
430 mVehicleHal.unsubscribeProperty(this, HAL_PROPERTY_ID);
431 }
432 mPublisherListeners.clear();
433 mSubscriberListeners.clear();
434 }
435
436 @Override
437 public Collection<VehiclePropConfig> takeSupportedProperties(
438 Collection<VehiclePropConfig> allProperties) {
439 List<VehiclePropConfig> taken = new LinkedList<>();
440 for (VehiclePropConfig p : allProperties) {
441 if (p.prop == HAL_PROPERTY_ID) {
442 taken.add(p);
443 mIsSupported = true;
444 if (DBG) {
445 Log.d(TAG, "takeSupportedProperties: " + toHexString(p.prop));
446 }
447 break;
448 }
449 }
450 return taken;
451 }
452
453 /**
454 * Consumes/produces HAL messages. The format of these messages is defined in:
455 * hardware/interfaces/automotive/vehicle/2.1/types.hal
456 */
457 @Override
458 public void handleHalEvents(List<VehiclePropValue> values) {
459 if (DBG) {
460 Log.d(TAG, "Handling a VMS property change");
461 }
462 for (VehiclePropValue v : values) {
463 ArrayList<Integer> vec = v.value.int32Values;
464 int messageType = vec.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE);
465
466 if (DBG) {
467 Log.d(TAG, "Handling VMS message type: " + messageType);
468 }
469 switch (messageType) {
470 case VmsMessageType.DATA:
471 handleDataEvent(vec, toByteArray(v.value.bytes));
472 break;
473 case VmsMessageType.SUBSCRIBE:
474 handleSubscribeEvent(vec);
475 break;
476 case VmsMessageType.UNSUBSCRIBE:
477 handleUnsubscribeEvent(vec);
478 break;
479 case VmsMessageType.SUBSCRIBE_TO_PUBLISHER:
480 handleSubscribeToPublisherEvent(vec);
481 break;
482 case VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER:
483 handleUnsubscribeFromPublisherEvent(vec);
484 break;
485 case VmsMessageType.OFFERING:
486 handleOfferingEvent(vec);
487 break;
488 case VmsMessageType.AVAILABILITY_REQUEST:
489 handleHalAvailabilityRequestEvent();
490 break;
491 case VmsMessageType.SUBSCRIPTIONS_REQUEST:
492 handleSubscriptionRequestEvent();
493 break;
494 default:
495 throw new IllegalArgumentException("Unexpected message type: " + messageType);
496 }
497 }
498 }
499
500 private VmsLayer parseVmsLayerFromSimpleMessageIntegerValues(List<Integer> integerValues) {
501 return new VmsLayer(integerValues.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_TYPE),
502 integerValues.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_SUBTYPE),
503 integerValues.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_VERSION));
504 }
505
506 private VmsLayer parseVmsLayerFromDataMessageIntegerValues(List<Integer> integerValues) {
507 return parseVmsLayerFromSimpleMessageIntegerValues(integerValues);
508 }
509
510 private int parsePublisherIdFromDataMessageIntegerValues(List<Integer> integerValues) {
511 return integerValues.get(VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.PUBLISHER_ID);
512 }
513
514
515 /**
516 * Data message format:
517 * <ul>
518 * <li>Message type.
519 * <li>Layer id.
520 * <li>Layer version.
521 * <li>Layer subtype.
522 * <li>Publisher ID.
523 * <li>Payload.
524 * </ul>
525 */
526 private void handleDataEvent(List<Integer> integerValues, byte[] payload) {
527 VmsLayer vmsLayer = parseVmsLayerFromDataMessageIntegerValues(integerValues);
528 int publisherId = parsePublisherIdFromDataMessageIntegerValues(integerValues);
529 if (DBG) {
530 Log.d(TAG, "Handling a data event for Layer: " + vmsLayer);
531 }
532
533 // Send the message.
534 for (VmsHalSubscriberListener listener : mSubscriberListeners) {
535 listener.onDataMessage(vmsLayer, publisherId, payload);
536 }
537 }
538
539 /**
540 * Subscribe message format:
541 * <ul>
542 * <li>Message type.
543 * <li>Layer id.
544 * <li>Layer version.
545 * <li>Layer subtype.
546 * </ul>
547 */
548 private void handleSubscribeEvent(List<Integer> integerValues) {
549 VmsLayer vmsLayer = parseVmsLayerFromSimpleMessageIntegerValues(integerValues);
550 if (DBG) {
551 Log.d(TAG, "Handling a subscribe event for Layer: " + vmsLayer);
552 }
553 addHalSubscription(vmsLayer);
554 }
555
556 /**
557 * Subscribe message format:
558 * <ul>
559 * <li>Message type.
560 * <li>Layer id.
561 * <li>Layer version.
562 * <li>Layer subtype.
563 * <li>Publisher ID
564 * </ul>
565 */
566 private void handleSubscribeToPublisherEvent(List<Integer> integerValues) {
567 VmsLayer vmsLayer = parseVmsLayerFromSimpleMessageIntegerValues(integerValues);
568 if (DBG) {
569 Log.d(TAG, "Handling a subscribe event for Layer: " + vmsLayer);
570 }
571 int publisherId =
572 integerValues.get(VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.PUBLISHER_ID);
573 addHalSubscriptionToPublisher(vmsLayer, publisherId);
574 }
575
576 /**
577 * Unsubscribe message format:
578 * <ul>
579 * <li>Message type.
580 * <li>Layer id.
581 * <li>Layer version.
582 * </ul>
583 */
584 private void handleUnsubscribeEvent(List<Integer> integerValues) {
585 VmsLayer vmsLayer = parseVmsLayerFromSimpleMessageIntegerValues(integerValues);
586 if (DBG) {
587 Log.d(TAG, "Handling an unsubscribe event for Layer: " + vmsLayer);
588 }
589 removeHalSubscription(vmsLayer);
590 }
591
592 /**
593 * Unsubscribe message format:
594 * <ul>
595 * <li>Message type.
596 * <li>Layer id.
597 * <li>Layer version.
598 * </ul>
599 */
600 private void handleUnsubscribeFromPublisherEvent(List<Integer> integerValues) {
601 VmsLayer vmsLayer = parseVmsLayerFromSimpleMessageIntegerValues(integerValues);
602 int publisherId =
603 integerValues.get(VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.PUBLISHER_ID);
604 if (DBG) {
605 Log.d(TAG, "Handling an unsubscribe event for Layer: " + vmsLayer);
606 }
607 removeHalSubscriptionFromPublisher(vmsLayer, publisherId);
608 }
609
610 private static int NUM_INTEGERS_IN_VMS_LAYER = 3;
611
612 private VmsLayer parseVmsLayerFromIndex(List<Integer> integerValues, int index) {
613 int layerType = integerValues.get(index++);
614 int layerSutype = integerValues.get(index++);
615 int layerVersion = integerValues.get(index++);
616 return new VmsLayer(layerType, layerSutype, layerVersion);
617 }
618
619 /**
620 * Offering message format:
621 * <ul>
622 * <li>Message type.
623 * <li>Publisher ID.
624 * <li>Number of offerings.
625 * <li>Each offering consists of:
626 * <ul>
627 * <li>Layer id.
628 * <li>Layer version.
629 * <li>Number of layer dependencies.
630 * <li>Layer type/subtype/version.
631 * </ul>
632 * </ul>
633 */
634 private void handleOfferingEvent(List<Integer> integerValues) {
635 int publisherId = integerValues.get(VmsOfferingMessageIntegerValuesIndex.PUBLISHER_ID);
636 int numLayersDependencies =
637 integerValues.get(
638 VmsOfferingMessageIntegerValuesIndex.NUMBER_OF_OFFERS);
639 int idx = VmsOfferingMessageIntegerValuesIndex.OFFERING_START;
640
641 Set<VmsLayerDependency> offeredLayers = new HashSet<>();
642
643 // An offering is layerId, LayerVersion, LayerType, NumDeps, <LayerId, LayerVersion> X NumDeps.
644 for (int i = 0; i < numLayersDependencies; i++) {
645 VmsLayer offeredLayer = parseVmsLayerFromIndex(integerValues, idx);
646 idx += NUM_INTEGERS_IN_VMS_LAYER;
647
648 int numDependenciesForLayer = integerValues.get(idx++);
649 if (numDependenciesForLayer == 0) {
650 offeredLayers.add(new VmsLayerDependency(offeredLayer));
651 } else {
652 Set<VmsLayer> dependencies = new HashSet<>();
653
654 for (int j = 0; j < numDependenciesForLayer; j++) {
655 VmsLayer dependantLayer = parseVmsLayerFromIndex(integerValues, idx);
656 idx += NUM_INTEGERS_IN_VMS_LAYER;
657 dependencies.add(dependantLayer);
658 }
659 offeredLayers.add(new VmsLayerDependency(offeredLayer, dependencies));
660 }
661 }
662 // Store the HAL offering.
663 VmsLayersOffering offering = new VmsLayersOffering(offeredLayers, publisherId);
664 synchronized (mLock) {
665 updateOffering(mHalPublisherToken, offering);
666 VmsOperationRecorder.get().setHalPublisherLayersOffering(offering);
667 }
668 }
669
670 /**
671 * Availability message format:
672 * <ul>
673 * <li>Message type.
674 * <li>Number of layers.
675 * <li>Layer type/subtype/version.
676 * </ul>
677 */
678 private void handleHalAvailabilityRequestEvent() {
679 synchronized (mLock) {
680 Collection<VmsAssociatedLayer> availableLayers = mAvailableLayers.getAvailableLayers();
681 VehiclePropValue vehiclePropertyValue =
682 toAvailabilityUpdateVehiclePropValue(
683 availableLayers,
684 VmsMessageType.AVAILABILITY_RESPONSE);
685
686 setPropertyValue(vehiclePropertyValue);
687 }
688 }
689
690 /**
691 * VmsSubscriptionRequestFormat:
692 * <ul>
693 * <li>Message type.
694 * </ul>
695 * <p>
696 * VmsSubscriptionResponseFormat:
697 * <ul>
698 * <li>Message type.
699 * <li>Sequence number.
700 * <li>Number of layers.
701 * <li>Layer type/subtype/version.
702 * </ul>
703 */
704 private void handleSubscriptionRequestEvent() {
705 VmsSubscriptionState subscription = getSubscriptionState();
706 VehiclePropValue vehicleProp =
707 toTypedVmsVehiclePropValue(VmsMessageType.SUBSCRIPTIONS_RESPONSE);
708 VehiclePropValue.RawValue v = vehicleProp.value;
709 v.int32Values.add(subscription.getSequenceNumber());
710 Set<VmsLayer> layers = subscription.getLayers();
711 v.int32Values.add(layers.size());
712
713 //TODO(asafro): get the real number of associated layers in the subscriptions
714 // state and send the associated layers themselves.
715 v.int32Values.add(0);
716
717 for (VmsLayer layer : layers) {
718 v.int32Values.add(layer.getType());
719 v.int32Values.add(layer.getSubtype());
720 v.int32Values.add(layer.getVersion());
721 }
722 setPropertyValue(vehicleProp);
723 }
724
725 private void updateOffering(IBinder publisherToken, VmsLayersOffering offering) {
726 Set<VmsAssociatedLayer> availableLayers = Collections.EMPTY_SET;
727 synchronized (mLock) {
728 mOfferings.put(publisherToken, offering);
729
730 // Update layers availability.
731 mAvailableLayers.setPublishersOffering(mOfferings.values());
732
733 availableLayers = mAvailableLayers.getAvailableLayers();
734 }
735 notifyOfAvailabilityChange(availableLayers);
736 }
737
738 @Override
739 public void dump(PrintWriter writer) {
740 writer.println(TAG);
741 writer.println("VmsProperty " + (mIsSupported ? "" : "not") + " supported.");
742 }
743
744 /**
745 * Updates the VMS HAL property with the given value.
746 *
747 * @param layer layer data to update the hal property.
748 * @param hasSubscribers if it is a subscribe or unsubscribe message.
749 * @return true if the call to the HAL to update the property was successful.
750 */
751 public boolean setSubscriptionRequest(VmsLayer layer, boolean hasSubscribers) {
752 VehiclePropValue vehiclePropertyValue = toTypedVmsVehiclePropValueWithLayer(
753 hasSubscribers ? VmsMessageType.SUBSCRIBE : VmsMessageType.UNSUBSCRIBE, layer);
754 return setPropertyValue(vehiclePropertyValue);
755 }
756
757 public boolean setSubscriptionToPublisherRequest(VmsLayer layer,
758 int publisherId,
759 boolean hasSubscribers) {
760 VehiclePropValue vehiclePropertyValue = toTypedVmsVehiclePropValueWithLayer(
761 hasSubscribers ?
762 VmsMessageType.SUBSCRIBE_TO_PUBLISHER :
763 VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER, layer);
764 vehiclePropertyValue.value.int32Values.add(publisherId);
765 return setPropertyValue(vehiclePropertyValue);
766 }
767
768 public boolean setDataMessage(VmsLayer layer, byte[] payload) {
769 VehiclePropValue vehiclePropertyValue =
770 toTypedVmsVehiclePropValueWithLayer(VmsMessageType.DATA, layer);
771 VehiclePropValue.RawValue v = vehiclePropertyValue.value;
772 v.bytes.ensureCapacity(payload.length);
773 for (byte b : payload) {
774 v.bytes.add(b);
775 }
776 return setPropertyValue(vehiclePropertyValue);
777 }
778
779 public boolean notifyAvailabilityChangeToHal(Collection<VmsAssociatedLayer> availableLayers) {
780 VehiclePropValue vehiclePropertyValue =
781 toAvailabilityUpdateVehiclePropValue(
782 availableLayers,
783 VmsMessageType.AVAILABILITY_CHANGE);
784
785 return setPropertyValue(vehiclePropertyValue);
786 }
787
788 public boolean setPropertyValue(VehiclePropValue vehiclePropertyValue) {
789 try {
790 mVehicleHal.set(vehiclePropertyValue);
791 return true;
792 } catch (PropertyTimeoutException e) {
793 Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(HAL_PROPERTY_ID));
794 }
795 return false;
796 }
797
798 private static VehiclePropValue toTypedVmsVehiclePropValue(int messageType) {
799 VehiclePropValue vehicleProp = new VehiclePropValue();
800 vehicleProp.prop = HAL_PROPERTY_ID;
801 vehicleProp.areaId = VehicleAreaType.VEHICLE_AREA_TYPE_NONE;
802 VehiclePropValue.RawValue v = vehicleProp.value;
803
804 v.int32Values.add(messageType);
805 return vehicleProp;
806 }
807
808 /**
809 * Creates a {@link VehiclePropValue}
810 */
811 private static VehiclePropValue toTypedVmsVehiclePropValueWithLayer(
812 int messageType, VmsLayer layer) {
813 VehiclePropValue vehicleProp = toTypedVmsVehiclePropValue(messageType);
814 VehiclePropValue.RawValue v = vehicleProp.value;
815 v.int32Values.add(layer.getType());
816 v.int32Values.add(layer.getSubtype());
817 v.int32Values.add(layer.getVersion());
818 return vehicleProp;
819 }
820
821 private static VehiclePropValue toAvailabilityUpdateVehiclePropValue(
822 Collection<VmsAssociatedLayer> availableAssociatedLayers, int messageType) {
823
824 if (!AVAILABILITY_MESSAGE_TYPES.contains(messageType)) {
825 throw new IllegalArgumentException("Unsupported availability type: " + messageType);
826 }
827 VehiclePropValue vehicleProp =
828 toTypedVmsVehiclePropValue(messageType);
829 populateAvailabilityPropValueFields(availableAssociatedLayers, vehicleProp);
830 return vehicleProp;
831
832 }
833
834 private static void populateAvailabilityPropValueFields(
835 Collection<VmsAssociatedLayer> availableAssociatedLayers,
836 VehiclePropValue vehicleProp) {
837 VehiclePropValue.RawValue v = vehicleProp.value;
838 int numLayers = availableAssociatedLayers.size();
839 v.int32Values.add(numLayers);
840 for (VmsAssociatedLayer layer : availableAssociatedLayers) {
841 v.int32Values.add(layer.getVmsLayer().getType());
842 v.int32Values.add(layer.getVmsLayer().getSubtype());
843 v.int32Values.add(layer.getVmsLayer().getVersion());
844 v.int32Values.add(layer.getPublisherIds().size());
845 for (int publisherId : layer.getPublisherIds()) {
846 v.int32Values.add(publisherId);
847 }
848 }
849 }
850}
diff --git a/tests/VmsPublisherClientSample/Android.mk b/tests/VmsPublisherClientSample/Android.mk
deleted file mode 100644
index 2aa6c401..00000000
--- a/tests/VmsPublisherClientSample/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
1# Copyright (C) 2017 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15#
16
17LOCAL_PATH:= $(call my-dir)
18
19include $(CLEAR_VARS)
20
21LOCAL_SRC_FILES := $(call all-java-files-under, src)
22
23LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
24
25LOCAL_PACKAGE_NAME := VmsPublisherClientSample
26
27LOCAL_MODULE_TAGS := optional
28
29LOCAL_PRIVILEGED_MODULE := true
30
31LOCAL_CERTIFICATE := testkey
32
33LOCAL_PROGUARD_ENABLED := disabled
34
35LOCAL_JAVA_LIBRARIES += android.car
36
37include $(BUILD_PACKAGE) \ No newline at end of file
diff --git a/tests/VmsPublisherClientSample/AndroidManifest.xml b/tests/VmsPublisherClientSample/AndroidManifest.xml
deleted file mode 100644
index fdc1a318..00000000
--- a/tests/VmsPublisherClientSample/AndroidManifest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
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<manifest xmlns:android="http://schemas.android.com/apk/res/android"
18 package="com.google.android.car.vms.publisher">
19
20 <uses-permission android:name="android.car.permission.VMS_PUBLISHER" />
21 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
22 <uses-permission android:name="android.permission.CAMERA"/>
23
24 <uses-sdk android:minSdkVersion="25" android:targetSdkVersion='25'/>
25
26 <application android:label="@string/app_name"
27 android:icon="@mipmap/ic_launcher"
28 android:directBootAware="true">
29 <service android:name=".VmsPublisherClientSampleService"
30 android:exported="true"
31 android:singleUser="true">
32 </service>
33 </application>
34</manifest>
diff --git a/tests/VmsPublisherClientSample/res/mipmap-hdpi/ic_launcher.png b/tests/VmsPublisherClientSample/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index cde69bcc..00000000
--- a/tests/VmsPublisherClientSample/res/mipmap-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsPublisherClientSample/res/mipmap-mdpi/ic_launcher.png b/tests/VmsPublisherClientSample/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index c133a0cb..00000000
--- a/tests/VmsPublisherClientSample/res/mipmap-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsPublisherClientSample/res/mipmap-xhdpi/ic_launcher.png b/tests/VmsPublisherClientSample/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index bfa42f0e..00000000
--- a/tests/VmsPublisherClientSample/res/mipmap-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsPublisherClientSample/res/mipmap-xxhdpi/ic_launcher.png b/tests/VmsPublisherClientSample/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 324e72cd..00000000
--- a/tests/VmsPublisherClientSample/res/mipmap-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsPublisherClientSample/res/mipmap-xxxhdpi/ic_launcher.png b/tests/VmsPublisherClientSample/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index aee44e13..00000000
--- a/tests/VmsPublisherClientSample/res/mipmap-xxxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsPublisherClientSample/res/values/strings.xml b/tests/VmsPublisherClientSample/res/values/strings.xml
deleted file mode 100644
index df8bf057..00000000
--- a/tests/VmsPublisherClientSample/res/values/strings.xml
+++ /dev/null
@@ -1,18 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
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<resources>
17 <string name="app_name">VmsPublisherClientSample</string>
18</resources>
diff --git a/tests/VmsPublisherClientSample/src/com/google/android/car/vms/publisher/VmsPublisherClientSampleService.java b/tests/VmsPublisherClientSample/src/com/google/android/car/vms/publisher/VmsPublisherClientSampleService.java
deleted file mode 100644
index e235f1e9..00000000
--- a/tests/VmsPublisherClientSample/src/com/google/android/car/vms/publisher/VmsPublisherClientSampleService.java
+++ /dev/null
@@ -1,81 +0,0 @@
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
17package com.google.android.car.vms.publisher;
18
19import android.car.vms.VmsLayer;
20import android.car.vms.VmsPublisherClientService;
21import android.car.vms.VmsSubscriptionState;
22import android.os.Handler;
23import android.os.Message;
24
25import java.util.concurrent.atomic.AtomicBoolean;
26
27/**
28 * This service is launched during the initialization of the VMS publisher service.
29 * Once onVmsPublisherServiceReady is invoked, it starts publishing a single byte every second.
30 */
31public class VmsPublisherClientSampleService extends VmsPublisherClientService {
32 public static final int PUBLISH_EVENT = 0;
33 public static final VmsLayer TEST_LAYER = new VmsLayer(0, 0, 0);
34 public static final int PUBLISHER_ID = 1;
35
36 private byte mCounter = 0;
37 private AtomicBoolean mInitialized = new AtomicBoolean(false);
38
39 private final Handler mHandler = new Handler() {
40 @Override
41 public void handleMessage(Message msg) {
42 if (msg.what == PUBLISH_EVENT && mInitialized.get()) {
43 periodicPublish();
44 }
45 }
46 };
47
48 /**
49 * Notifies that the publisher services are ready to be used: {@link #publish(VmsLayer, byte[])}
50 * and {@link #getSubscriptions()}.
51 */
52 @Override
53 public void onVmsPublisherServiceReady() {
54 VmsSubscriptionState subscriptionState = getSubscriptions();
55 onVmsSubscriptionChange(subscriptionState);
56 }
57
58 @Override
59 public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) {
60 if (mInitialized.compareAndSet(false, true)) {
61 for (VmsLayer layer : subscriptionState.getLayers()) {
62 if (layer.equals(TEST_LAYER)) {
63 mHandler.sendEmptyMessage(PUBLISH_EVENT);
64 }
65 }
66 }
67 }
68
69 @Override
70 public void onDestroy() {
71 super.onDestroy();
72 mInitialized.set(false);
73 mHandler.removeMessages(PUBLISH_EVENT);
74 }
75
76 private void periodicPublish() {
77 publish(TEST_LAYER, PUBLISHER_ID, new byte[]{mCounter});
78 ++mCounter;
79 mHandler.sendEmptyMessageDelayed(PUBLISH_EVENT, 1000);
80 }
81}
diff --git a/tests/VmsSubscriberClientSample/Android.mk b/tests/VmsSubscriberClientSample/Android.mk
deleted file mode 100644
index f59e2679..00000000
--- a/tests/VmsSubscriberClientSample/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
1# Copyright (C) 2017 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15#
16
17LOCAL_PATH:= $(call my-dir)
18
19include $(CLEAR_VARS)
20
21LOCAL_SRC_FILES := $(call all-java-files-under, src)
22
23LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
24
25LOCAL_PACKAGE_NAME := VmsSubscriberClientSample
26
27LOCAL_MODULE_TAGS := optional
28
29LOCAL_PRIVILEGED_MODULE := true
30
31LOCAL_CERTIFICATE := platform
32
33LOCAL_PROGUARD_ENABLED := disabled
34
35LOCAL_JAVA_LIBRARIES += android.car
36
37include packages/services/Car/car-support-lib/car-support.mk
38
39include $(BUILD_PACKAGE) \ No newline at end of file
diff --git a/tests/VmsSubscriberClientSample/AndroidManifest.xml b/tests/VmsSubscriberClientSample/AndroidManifest.xml
deleted file mode 100644
index bc798d77..00000000
--- a/tests/VmsSubscriberClientSample/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
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<manifest xmlns:android="http://schemas.android.com/apk/res/android"
18 xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
19 package="com.google.android.car.vms.subscriber"
20 android:sharedUserId="android.uid.system">
21 <uses-sdk android:minSdkVersion="25" android:targetSdkVersion='25'/>
22
23 <application android:label="@string/app_name"
24 android:icon="@mipmap/ic_launcher">
25 <meta-data
26 android:name="android.car.application"
27 android:resource="@xml/automotive_app_desc"/>
28 <activity android:name=".VmsSubscriberClientSampleActivity">
29 <intent-filter>
30 <action android:name="android.intent.action.MAIN"/>
31 <category android:name="android.intent.category.LAUNCHER"/>
32 </intent-filter>
33 </activity>
34 </application>
35</manifest> \ No newline at end of file
diff --git a/tests/VmsSubscriberClientSample/res/layout/activity_main.xml b/tests/VmsSubscriberClientSample/res/layout/activity_main.xml
deleted file mode 100644
index ce05a4d2..00000000
--- a/tests/VmsSubscriberClientSample/res/layout/activity_main.xml
+++ /dev/null
@@ -1,20 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<RelativeLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:id="@+id/activity_main"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 android:paddingTop="@dimen/activity_vertical_margin"
9 android:paddingBottom="@dimen/activity_vertical_margin"
10 android:paddingLeft="@dimen/activity_horizontal_margin"
11 android:paddingRight="@dimen/activity_horizontal_margin"
12 tools:context="vms.apps.android.google.com.java.myapplication.MainActivity">
13
14 <TextView
15 android:layout_width="match_parent"
16 android:layout_height="wrap_content"
17 android:textAppearance="?android:attr/textAppearanceLarge"
18 android:text=""
19 android:id="@+id/textview"/>
20</RelativeLayout>
diff --git a/tests/VmsSubscriberClientSample/res/mipmap-hdpi/ic_launcher.png b/tests/VmsSubscriberClientSample/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index cde69bcc..00000000
--- a/tests/VmsSubscriberClientSample/res/mipmap-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsSubscriberClientSample/res/mipmap-mdpi/ic_launcher.png b/tests/VmsSubscriberClientSample/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index c133a0cb..00000000
--- a/tests/VmsSubscriberClientSample/res/mipmap-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsSubscriberClientSample/res/mipmap-xhdpi/ic_launcher.png b/tests/VmsSubscriberClientSample/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index bfa42f0e..00000000
--- a/tests/VmsSubscriberClientSample/res/mipmap-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsSubscriberClientSample/res/mipmap-xxhdpi/ic_launcher.png b/tests/VmsSubscriberClientSample/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 324e72cd..00000000
--- a/tests/VmsSubscriberClientSample/res/mipmap-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsSubscriberClientSample/res/mipmap-xxxhdpi/ic_launcher.png b/tests/VmsSubscriberClientSample/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index aee44e13..00000000
--- a/tests/VmsSubscriberClientSample/res/mipmap-xxxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/VmsSubscriberClientSample/res/values-w820dp/dimens.xml b/tests/VmsSubscriberClientSample/res/values-w820dp/dimens.xml
deleted file mode 100644
index 308a1947..00000000
--- a/tests/VmsSubscriberClientSample/res/values-w820dp/dimens.xml
+++ /dev/null
@@ -1,6 +0,0 @@
1<resources>
2 <!-- Example customization of dimensions originally defined in res/values/dimens.xml
3 (such as screen margins) for screens with more than 820dp of available width. This
4 would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
5 <dimen name="activity_horizontal_margin">64dp</dimen>
6</resources>
diff --git a/tests/VmsSubscriberClientSample/res/values/colors.xml b/tests/VmsSubscriberClientSample/res/values/colors.xml
deleted file mode 100644
index 5a077b3a..00000000
--- a/tests/VmsSubscriberClientSample/res/values/colors.xml
+++ /dev/null
@@ -1,6 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<resources>
3 <color name="colorPrimary">#3F51B5</color>
4 <color name="colorPrimaryDark">#303F9F</color>
5 <color name="colorAccent">#FF4081</color>
6</resources>
diff --git a/tests/VmsSubscriberClientSample/res/values/dimens.xml b/tests/VmsSubscriberClientSample/res/values/dimens.xml
deleted file mode 100644
index acf94cc6..00000000
--- a/tests/VmsSubscriberClientSample/res/values/dimens.xml
+++ /dev/null
@@ -1,5 +0,0 @@
1<resources>
2 <!-- Default screen margins, per the Android Design guidelines. -->
3 <dimen name="activity_horizontal_margin">16dp</dimen>
4 <dimen name="activity_vertical_margin">16dp</dimen>
5</resources>
diff --git a/tests/VmsSubscriberClientSample/res/values/strings.xml b/tests/VmsSubscriberClientSample/res/values/strings.xml
deleted file mode 100644
index 24df55ea..00000000
--- a/tests/VmsSubscriberClientSample/res/values/strings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
1<resources>
2 <string name="app_name">VmsSubscriberClientSample</string>
3</resources>
diff --git a/tests/VmsSubscriberClientSample/res/values/styles.xml b/tests/VmsSubscriberClientSample/res/values/styles.xml
deleted file mode 100644
index a7a06158..00000000
--- a/tests/VmsSubscriberClientSample/res/values/styles.xml
+++ /dev/null
@@ -1,8 +0,0 @@
1<resources>
2
3 <!-- Base application theme. -->
4 <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
5 <!-- Customize your theme here. -->
6 </style>
7
8</resources>
diff --git a/tests/VmsSubscriberClientSample/res/xml/automotive_app_desc.xml b/tests/VmsSubscriberClientSample/res/xml/automotive_app_desc.xml
deleted file mode 100644
index b10ddd01..00000000
--- a/tests/VmsSubscriberClientSample/res/xml/automotive_app_desc.xml
+++ /dev/null
@@ -1,20 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (C) 2015 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<automotiveApp>
17 <uses name="service" />
18 <uses name="projection" />
19 <uses name="activity" class="com.google.android.car.vms.subscriber.VmsSubscriberClientSampleActivity" />
20</automotiveApp>
diff --git a/tests/VmsSubscriberClientSample/src/com/google/android/car/vms/subscriber/VmsSubscriberClientSampleActivity.java b/tests/VmsSubscriberClientSample/src/com/google/android/car/vms/subscriber/VmsSubscriberClientSampleActivity.java
deleted file mode 100644
index 3ac07072..00000000
--- a/tests/VmsSubscriberClientSample/src/com/google/android/car/vms/subscriber/VmsSubscriberClientSampleActivity.java
+++ /dev/null
@@ -1,113 +0,0 @@
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
17package com.google.android.car.vms.subscriber;
18
19import android.app.Activity;
20import android.car.vms.VmsLayer;
21import android.car.vms.VmsSubscriberManager;
22import android.content.pm.PackageManager;
23import android.os.Bundle;
24import android.support.car.Car;
25import android.support.car.CarConnectionCallback;
26import android.util.Log;
27import android.widget.TextView;
28
29import java.util.List;
30
31/**
32 * Connects to the Car service during onCreate. CarConnectionCallback.onConnected is invoked when
33 * the connection is ready. Then, it subscribes to a VMS layer/version and updates the TextView when
34 * a message is received.
35 */
36public class VmsSubscriberClientSampleActivity extends Activity {
37 private static final String TAG = "VmsSampleActivity";
38 // The layer id and version should match the ones defined in
39 // com.google.android.car.vms.publisher.VmsPublisherClientSampleService
40 public static final VmsLayer TEST_LAYER = new VmsLayer(0, 0, 0);
41
42 private Car mCarApi;
43 private TextView mTextView;
44 private VmsSubscriberManager mVmsSubscriberManager;
45
46 @Override
47 protected void onCreate(Bundle savedInstanceState) {
48 super.onCreate(savedInstanceState);
49 setContentView(R.layout.activity_main);
50 mTextView = (TextView) findViewById(R.id.textview);
51 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
52 mCarApi = Car.createCar(this, mCarConnectionCallback);
53 mCarApi.connect();
54 } else {
55 Log.d(TAG, "No automotive feature.");
56 }
57 }
58
59 @Override
60 protected void onDestroy() {
61 super.onDestroy();
62 if (mCarApi != null) {
63 mCarApi.disconnect();
64 }
65 Log.i(TAG, "onDestroy");
66 }
67
68 private final CarConnectionCallback mCarConnectionCallback = new CarConnectionCallback() {
69 @Override
70 public void onConnected(Car car) {
71 Log.d(TAG, "Connected to Car Service");
72 mVmsSubscriberManager = getVmsSubscriberManager();
73 configureSubscriptions(mVmsSubscriberManager);
74 }
75
76 @Override
77 public void onDisconnected(Car car) {
78 Log.d(TAG, "Disconnect from Car Service");
79 }
80
81 private VmsSubscriberManager getVmsSubscriberManager() {
82 try {
83 return (VmsSubscriberManager) mCarApi.getCarManager(
84 android.car.Car.VMS_SUBSCRIBER_SERVICE);
85 } catch (android.support.car.CarNotConnectedException e) {
86 Log.e(TAG, "Car is not connected!", e);
87 }
88 return null;
89 }
90
91 private void configureSubscriptions(VmsSubscriberManager vmsSubscriberManager) {
92 try {
93 vmsSubscriberManager.registerClientCallback(mClientCallback);
94 vmsSubscriberManager.subscribe(TEST_LAYER);
95 } catch (android.car.CarNotConnectedException e) {
96 Log.e(TAG, "Car is not connected!", e);
97 }
98 }
99 };
100
101 private final VmsSubscriberManager.VmsSubscriberClientCallback mClientCallback =
102 new VmsSubscriberManager.VmsSubscriberClientCallback() {
103 @Override
104 public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
105 mTextView.setText(String.valueOf(payload[0]));
106 }
107
108 @Override
109 public void onLayersAvailabilityChanged(List<VmsLayer> availableLayers) {
110 mTextView.setText(String.valueOf(availableLayers));
111 }
112 };
113}
diff --git a/tests/carservice_test/AndroidManifest.xml b/tests/carservice_test/AndroidManifest.xml
index 6f7ba349..6a1e2bfc 100644
--- a/tests/carservice_test/AndroidManifest.xml
+++ b/tests/carservice_test/AndroidManifest.xml
@@ -43,9 +43,5 @@
43 android:process="com.android.car.carservicetest.activityC"/> 43 android:process="com.android.car.carservicetest.activityC"/>
44 <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$BlockingActivity" 44 <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$BlockingActivity"
45 android:taskAffinity="com.android.car.carservicetest.block"/> 45 android:taskAffinity="com.android.car.carservicetest.block"/>
46 <service android:name=".SimpleVmsPublisherClientService"
47 android:exported="true"
48 />
49 <service android:name=".VmsPublisherClientMockService" android:exported="true" />
50 </application> 46 </application>
51</manifest> 47</manifest>
diff --git a/tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java b/tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java
deleted file mode 100644
index c3c15f5b..00000000
--- a/tests/carservice_test/src/com/android/car/test/SimpleVmsPublisherClientService.java
+++ /dev/null
@@ -1,40 +0,0 @@
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
17package com.android.car.test;
18
19import android.car.annotation.FutureFeature;
20import android.car.vms.VmsPublisherClientService;
21import android.car.vms.VmsSubscriptionState;
22
23/**
24 * This service is launched during the tests in VmsPublisherClientServiceTest.
25 */
26@FutureFeature
27public class SimpleVmsPublisherClientService extends VmsPublisherClientService {
28 @Override
29 public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) {
30
31 }
32
33 @Override
34 public void onVmsPublisherServiceReady() {
35 // Publish a property that is going to be verified in the test.
36 publish(VmsPublisherClientServiceTest.MOCK_PUBLISHER_LAYER,
37 VmsPublisherClientServiceTest.MOCK_PUBLISHER_ID,
38 VmsPublisherClientServiceTest.PAYLOAD);
39 }
40}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java b/tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java
deleted file mode 100644
index cad30860..00000000
--- a/tests/carservice_test/src/com/android/car/test/VmsHalServiceSubscriptionEventTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
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
17package com.android.car.test;
18
19import static org.junit.Assume.assumeTrue;
20
21import android.car.VehicleAreaType;
22import android.car.annotation.FutureFeature;
23import android.car.vms.VmsLayer;
24import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
25import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
26import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
27import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
28import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
29import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
30import android.hardware.automotive.vehicle.V2_0.VmsSubscriptionsStateIntegerValuesIndex;
31import android.test.suitebuilder.annotation.MediumTest;
32
33import com.android.car.vehiclehal.VehiclePropValueBuilder;
34import com.android.car.vehiclehal.test.MockedVehicleHal;
35import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
36
37import java.util.ArrayList;
38import java.util.Arrays;
39import java.util.HashSet;
40import java.util.List;
41import java.util.concurrent.Semaphore;
42import java.util.concurrent.TimeUnit;
43
44@FutureFeature
45@MediumTest
46public class VmsHalServiceSubscriptionEventTest extends MockedCarTestBase {
47 private static final String TAG = "VmsHalServiceTest";
48
49 private HalHandler mHalHandler;
50 private MockedVehicleHal mHal;
51 // Used to block until the HAL property is updated in HalHandler.onPropertySet.
52 private Semaphore mHalHandlerSemaphore;
53
54 @Override
55 protected synchronized void configureMockedHal() {
56 mHalHandler = new HalHandler();
57 addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
58 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
59 .setAccess(VehiclePropertyAccess.READ_WRITE)
60 .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
61 }
62
63 @Override
64 protected void setUp() throws Exception {
65 if (!VmsTestUtils.canRunTest(TAG)) return;
66 super.setUp();
67 mHal = getMockedVehicleHal();
68 mHalHandlerSemaphore = new Semaphore(0);
69 }
70
71 @Override
72 protected synchronized void tearDown() throws Exception {
73 if (!VmsTestUtils.canRunTest(TAG)) return;
74 super.tearDown();
75 }
76
77 public void testEmptySubscriptions() throws Exception {
78 if (!VmsTestUtils.canRunTest(TAG)) return;
79 List<VmsLayer> layers = new ArrayList<>();
80 subscriptionTestLogic(layers);
81 }
82
83 public void testOneSubscription() throws Exception {
84 if (!VmsTestUtils.canRunTest(TAG)) return;
85 List<VmsLayer> layers = Arrays.asList(new VmsLayer(8, 0, 3));
86 subscriptionTestLogic(layers);
87 }
88
89 public void testManySubscriptions() throws Exception {
90 if (!VmsTestUtils.canRunTest(TAG)) return;
91 List<VmsLayer> layers = Arrays.asList(
92 new VmsLayer(8, 1, 3),
93 new VmsLayer(5, 2, 1),
94 new VmsLayer(3, 3, 9),
95 new VmsLayer(2, 4, 7),
96 new VmsLayer(9, 5, 3));
97 subscriptionTestLogic(layers);
98 }
99
100 /**
101 * First, it subscribes to the given layers. Then it validates that a subscription request
102 * responds with the same layers.
103 */
104 private void subscriptionTestLogic(List<VmsLayer> layers) throws Exception {
105 for (VmsLayer layer : layers) {
106 subscribeViaHal(layer);
107 }
108 // Send subscription request.
109 mHal.injectEvent(createHalSubscriptionRequest());
110 // Wait for response.
111 assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
112 // Validate response.
113 ArrayList<Integer> v = mHalHandler.getValues();
114 int messageType = v.get(VmsSubscriptionsStateIntegerValuesIndex.MESSAGE_TYPE);
115 int sequenceNumber = v.get(VmsSubscriptionsStateIntegerValuesIndex.SEQUENCE_NUMBER);
116 int numberLayers = v.get(VmsSubscriptionsStateIntegerValuesIndex.NUMBER_OF_LAYERS);
117 assertEquals(VmsMessageType.SUBSCRIPTIONS_RESPONSE, messageType);
118 //TODO(asafro): This assertion makes no sense. need to fix.
119 //assertEquals(layers.size(), sequenceNumber);
120 assertEquals(layers.size(), numberLayers);
121 List<VmsLayer> receivedLayers = new ArrayList<>();
122 int start = VmsSubscriptionsStateIntegerValuesIndex.SUBSCRIPTIONS_START;
123 int end = VmsSubscriptionsStateIntegerValuesIndex.SUBSCRIPTIONS_START + 3 * numberLayers;
124 while (start < end) {
125 int type = v.get(start++);
126 int subtype = v.get(start++);
127 int version = v.get(start++);
128 receivedLayers.add(new VmsLayer(type, subtype, version));
129 }
130 assertEquals(new HashSet<>(layers), new HashSet<>(receivedLayers));
131 }
132
133 /**
134 * Subscribes to a layer, waits for the event to propagate back to the HAL layer and validates
135 * the propagated message.
136 */
137 private void subscribeViaHal(VmsLayer layer) throws Exception {
138 // Send subscribe request.
139 mHal.injectEvent(createHalSubscribeRequest(layer));
140 // Wait for response.
141 assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
142 // Validate response.
143 ArrayList<Integer> v = mHalHandler.getValues();
144 int messsageType = v.get(VmsMessageWithLayerIntegerValuesIndex.MESSAGE_TYPE);
145 int layerId = v.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_TYPE);
146 int layerVersion = v.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_VERSION);
147 int fused = v.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_SUBTYPE);
148 assertEquals(VmsMessageType.SUBSCRIBE, messsageType);
149 assertEquals(layer.getType(), layerId);
150 assertEquals(layer.getVersion(), layerVersion);
151 }
152
153 private VehiclePropValue createHalSubscribeRequest(VmsLayer layer) {
154 return VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
155 .addIntValue(VmsMessageType.SUBSCRIBE)
156 .addIntValue(layer.getType())
157 .addIntValue(layer.getSubtype())
158 .addIntValue(layer.getVersion())
159 .build();
160 }
161
162 private VehiclePropValue createHalSubscriptionRequest() {
163 return VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
164 .addIntValue(VmsMessageType.SUBSCRIPTIONS_REQUEST)
165 .build();
166 }
167
168 private class HalHandler implements VehicleHalPropertyHandler {
169 private ArrayList<Integer> mValues;
170
171 @Override
172 public synchronized void onPropertySet(VehiclePropValue value) {
173 mValues = value.value.int32Values;
174 mHalHandlerSemaphore.release();
175 }
176
177 public ArrayList<Integer> getValues() {
178 return mValues;
179 }
180 }
181} \ No newline at end of file
diff --git a/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java b/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
deleted file mode 100644
index 179a1945..00000000
--- a/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
+++ /dev/null
@@ -1,245 +0,0 @@
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
17package com.android.car.test;
18
19import android.car.vms.VmsLayer;
20import android.car.vms.VmsLayerDependency;
21import android.car.vms.VmsLayersOffering;
22import android.car.vms.VmsOperationRecorder;
23import android.test.suitebuilder.annotation.MediumTest;
24import android.util.Log;
25
26import junit.framework.TestCase;
27
28import org.json.JSONArray;
29import org.json.JSONException;
30import org.json.JSONObject;
31
32import java.util.ArrayList;
33import java.util.Arrays;
34import java.util.HashSet;
35
36@MediumTest
37public class VmsOperationRecorderTest extends TestCase {
38
39 /**
40 * Capture messages that VmsOperationRecorder.Writer would normally pass to Log.d(...).
41 */
42 class TestWriter extends VmsOperationRecorder.Writer {
43 public String mMsg;
44
45 @Override
46 public boolean isEnabled() {
47 return true;
48 }
49
50 @Override
51 public void write(String msg) {
52 super.write(msg);
53 mMsg = msg;
54 }
55 }
56
57 private TestWriter mWriter;
58 private VmsOperationRecorder mRecorder;
59 private static final String TAG = "VmsOperationRecorderTest";
60
61 private static final VmsLayer layer1 = new VmsLayer(1, 3, 2);
62 private static final VmsLayer layer2 = new VmsLayer(2, 4, 3);
63 private static final VmsLayer layer3 = new VmsLayer(3, 5, 4);
64
65 private static final VmsLayerDependency layerDependency1 = new VmsLayerDependency(layer3);
66 private static final VmsLayerDependency layerDependency2 = new VmsLayerDependency(layer1,
67 new HashSet<VmsLayer>(Arrays.asList(layer2, layer3)));
68
69 private static final VmsLayersOffering layersOffering0 = new VmsLayersOffering(
70 new HashSet<VmsLayerDependency>(), 66);
71 private static final VmsLayersOffering layersOffering1 = new VmsLayersOffering(
72 new HashSet<>(Arrays.asList(layerDependency1)), 66);
73 private static final VmsLayersOffering layersOffering2 = new VmsLayersOffering(
74 new HashSet<>(Arrays.asList(layerDependency1, layerDependency2)), 66);
75
76 public void setUp() {
77 mWriter = new TestWriter();
78 mRecorder = new VmsOperationRecorder(mWriter);
79 }
80
81 public void testSubscribe() throws Exception {
82 mRecorder.subscribe(layer1);
83 assertJsonMsgEquals("{'subscribe':{'layer':{'subtype':3,'type':1,'version':2}}}");
84 }
85
86 public void testUnsubscribe() throws Exception {
87 mRecorder.unsubscribe(layer1);
88 assertJsonMsgEquals("{'unsubscribe':{'layer':{'type':1,'subtype':3,'version':2}}}");
89 }
90
91 public void testStartMonitoring() throws Exception {
92 mRecorder.startMonitoring();
93 assertJsonMsgEquals("{'startMonitoring':{}}");
94 }
95
96 public void testStopMonitoring() throws Exception {
97 mRecorder.stopMonitoring();
98 assertJsonMsgEquals("{'stopMonitoring':{}}");
99 }
100
101 public void testSetLayersOffering0() throws Exception {
102 mRecorder.setLayersOffering(layersOffering0);
103 assertJsonMsgEquals("{'setLayersOffering':{}}");
104 }
105
106 public void testSetLayersOffering2() throws Exception {
107 mRecorder.setLayersOffering(layersOffering2);
108 assertJsonMsgEquals("{'setLayersOffering':{'layerDependency':["
109 + "{'layer':{'type':3,'subtype':5,'version':4}},"
110 + "{'layer':{'type':1,'subtype':3,'version':2},'dependency':["
111 + "{'type':2,'subtype':4,'version':3},{'type':3,'subtype':5,'version':4}]}"
112 + "]}}");
113 }
114
115 public void testGetPublisherId() throws Exception {
116 mRecorder.getPublisherId(9);
117 assertJsonMsgEquals("{'getPublisherId':{'publisherId':9}}");
118 }
119
120 public void testAddSubscription() throws Exception {
121 mRecorder.addSubscription(42, layer1);
122 assertJsonMsgEquals(
123 "{'addSubscription':{'sequenceNumber':42,'layer':{'type':1,'subtype':3,'version':2}}}"
124 );
125 }
126
127 public void testRemoveSubscription() throws Exception {
128 mRecorder.removeSubscription(42, layer1);
129 assertJsonMsgEquals("{'removeSubscription':"
130 + "{'sequenceNumber':42,'layer':{'type':1,'subtype':3,'version':2}}}");
131 }
132
133 public void testAddPromiscuousSubscription() throws Exception {
134 mRecorder.addPromiscuousSubscription(42);
135 assertJsonMsgEquals("{'addPromiscuousSubscription':{'sequenceNumber':42}}");
136 }
137
138 public void testRemovePromiscuousSubscription() throws Exception {
139 mRecorder.removePromiscuousSubscription(42);
140 assertJsonMsgEquals("{'removePromiscuousSubscription':{'sequenceNumber':42}}");
141 }
142
143 public void testAddHalSubscription() throws Exception {
144 mRecorder.addHalSubscription(42, layer1);
145 assertJsonMsgEquals("{'addHalSubscription':"
146 + "{'sequenceNumber':42,'layer':{'type':1,'subtype':3,'version':2}}}");
147 }
148
149 public void testRemoveHalSubscription() throws Exception {
150 mRecorder.removeHalSubscription(42, layer1);
151 assertJsonMsgEquals("{'removeHalSubscription':"
152 + "{'sequenceNumber':42,'layer':{'type':1,'subtype':3,'version':2}}}");
153 }
154
155 public void testSetPublisherLayersOffering() throws Exception {
156 mRecorder.setPublisherLayersOffering(layersOffering1);
157 assertJsonMsgEquals("{'setPublisherLayersOffering':{'layerDependency':["
158 + "{'layer':{'type':3,'subtype':5,'version':4}}]}}");
159 }
160
161 public void testSetHalPublisherLayersOffering() throws Exception {
162 mRecorder.setHalPublisherLayersOffering(layersOffering1);
163 assertJsonMsgEquals("{'setHalPublisherLayersOffering':{'layerDependency':["
164 + "{'layer':{'type':3,'subtype':5,'version':4}}]}}");
165 }
166
167 public void testSubscribeToPublisher() throws Exception {
168 mRecorder.subscribe(layer1, 99);
169 assertJsonMsgEquals(
170 "{'subscribe':{'publisherId':99, 'layer':{'type':1,'subtype':3,'version':2}}}");
171 }
172
173 public void testUnsubscribeToPublisher() throws Exception {
174 mRecorder.unsubscribe(layer1, 99);
175 assertJsonMsgEquals(
176 "{'unsubscribe':{'publisherId':99, 'layer':{'type':1,'subtype':3,'version':2}}}}");
177 }
178
179 private void assertJsonMsgEquals(String expectJson) throws Exception {
180 // Escaping double quotes in a JSON string is really noisy. The test data uses single
181 // quotes instead, which gets replaced here.
182 JSONObject expect = new JSONObject(expectJson.replace("'", "\""));
183 JSONObject got = new JSONObject(mWriter.mMsg);
184 assertTrue(similar(expect, got));
185 }
186
187 /*
188 * Determine if two JSONObjects are similar.
189 * They must contain the same set of names which must be associated with
190 * similar values.
191 */
192 private boolean similar(JSONObject expect, JSONObject got) {
193 try {
194 if (!expect.keySet().equals(got.keySet())) {
195 return false;
196 }
197
198 for (String key : expect.keySet()) {
199 Object valueExpect = expect.get(key);
200 Object valueGot = got.get(key);
201
202 if (valueExpect == valueGot) {
203 continue;
204 }
205
206 if (valueExpect == null) {
207 return false;
208 }
209
210 if (valueExpect instanceof JSONObject) {
211 return similar((JSONObject) valueExpect, (JSONObject) valueGot);
212 } else if (valueExpect instanceof JSONArray) {
213 // Equal JSONArray have the same length and one contains the other.
214 JSONArray expectArray = (JSONArray) valueExpect;
215 JSONArray gotArray = (JSONArray) valueGot;
216
217 if (expectArray.length() != gotArray.length()) {
218 return false;
219 }
220
221 for (int i = 0; i < expectArray.length(); i++) {
222 boolean gotContainsSimilar = false;
223 for (int j = 0; j < gotArray.length(); j++) {
224 if (similar((JSONObject) expectArray.get(i),
225 (JSONObject) gotArray.get(j))) {
226 gotContainsSimilar = true;
227 break;
228 }
229 }
230 if (!gotContainsSimilar) {
231 return false;
232 }
233 }
234 } else if (!valueExpect.equals(valueGot)) {
235 return false;
236 }
237 }
238
239 } catch (JSONException e) {
240 Log.d(TAG, "Could not compare JSONObjects: " + e);
241 return false;
242 }
243 return true;
244 }
245}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java b/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
deleted file mode 100644
index 0d5c4278..00000000
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
+++ /dev/null
@@ -1,94 +0,0 @@
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
17package com.android.car.test;
18
19import android.car.annotation.FutureFeature;
20import android.car.vms.VmsLayer;
21import android.car.vms.VmsLayerDependency;
22import android.car.vms.VmsLayersOffering;
23import android.car.vms.VmsPublisherClientService;
24import android.car.vms.VmsSubscriptionState;
25import android.util.Log;
26import java.util.ArrayList;
27import java.util.HashSet;
28import java.util.List;
29import java.util.Set;
30
31/**
32 * This service is launched during the tests in VmsPublisherSubscriberTest. It publishes a property
33 * that is going to be verified in the test.
34 *
35 * The service makes offering for pre-defined layers which verifies availability notifications for
36 * subscribers without them actively being subscribed to a layer, and also echos all the
37 * subscription requests with an offering for that layer.
38 * For example, without any subscription request from any client, this service will make offering
39 * to layer X. If a client will subscribe later to layer Y, this service will respond with offering
40 * to both layers X and Y.
41 *
42 * Note that the subscriber can subscribe before the publisher finishes initialization. To cover
43 * both potential scenarios, this service publishes the test message in onVmsSubscriptionChange
44 * and in onVmsPublisherServiceReady. See comments below.
45 */
46@FutureFeature
47public class VmsPublisherClientMockService extends VmsPublisherClientService {
48 private static final String TAG = "VmsPublisherClientMockService";
49
50 @Override
51 public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) {
52 // Case when the publisher finished initialization before the subscription request.
53 initializeMockPublisher(subscriptionState);
54 }
55
56 @Override
57 public void onVmsPublisherServiceReady() {
58 // Case when the subscription request was sent before the publisher was ready.
59 VmsSubscriptionState subscriptionState = getSubscriptions();
60 initializeMockPublisher(subscriptionState);
61 }
62
63 private void initializeMockPublisher(VmsSubscriptionState subscriptionState) {
64 Log.d(TAG, "Initializing Mock publisher");
65 int publisherId = getPublisherId(VmsPublisherSubscriberTest.PAYLOAD);
66 publishIfNeeded(subscriptionState);
67 declareOffering(subscriptionState, publisherId);
68 }
69
70 private void publishIfNeeded(VmsSubscriptionState subscriptionState) {
71 for (VmsLayer layer : subscriptionState.getLayers()) {
72 if (layer.equals(VmsPublisherSubscriberTest.LAYER)) {
73 publish(VmsPublisherSubscriberTest.LAYER,
74 VmsPublisherSubscriberTest.EXPECTED_PUBLISHER_ID,
75 VmsPublisherSubscriberTest.PAYLOAD);
76 }
77 }
78 }
79
80 private void declareOffering(VmsSubscriptionState subscriptionState, int publisherId) {
81 Set<VmsLayerDependency> dependencies = new HashSet<>();
82
83 // Add all layers from the subscription state.
84 for( VmsLayer layer : subscriptionState.getLayers()) {
85 dependencies.add(new VmsLayerDependency(layer));
86 }
87
88 // Add default test layers.
89 dependencies.add(new VmsLayerDependency(VmsPublisherSubscriberTest.LAYER));
90
91 VmsLayersOffering offering = new VmsLayersOffering(dependencies, publisherId);
92 setLayersOffering(offering);
93 }
94}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java b/tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java
deleted file mode 100644
index 053bab73..00000000
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientServiceTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
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
17package com.android.car.test;
18
19import android.annotation.ArrayRes;
20import android.car.VehicleAreaType;
21import android.car.annotation.FutureFeature;
22import android.car.vms.VmsLayer;
23import android.content.Context;
24import android.content.ContextWrapper;
25import android.content.pm.PackageManager;
26import android.content.res.Resources;
27import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
28import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
29import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
30import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
31import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
32import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
33import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
34import android.test.suitebuilder.annotation.MediumTest;
35import android.util.Log;
36
37import com.android.car.R;
38import com.android.car.vehiclehal.VehiclePropValueBuilder;
39import com.android.car.vehiclehal.test.MockedVehicleHal;
40import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
41
42import java.util.ArrayList;
43import java.util.Arrays;
44import java.util.concurrent.Semaphore;
45import java.util.concurrent.TimeUnit;
46
47@FutureFeature
48@MediumTest
49public class VmsPublisherClientServiceTest extends MockedCarTestBase {
50 private static final String TAG = "VmsPublisherTest";
51 private static final int MOCK_PUBLISHER_LAYER_ID = 12;
52 private static final int MOCK_PUBLISHER_LAYER_VERSION = 34;
53 private static final int MOCK_PUBLISHER_LAYER_SUBTYPE = 56;
54 public static final int MOCK_PUBLISHER_ID = 1234;
55 public static final VmsLayer MOCK_PUBLISHER_LAYER =
56 new VmsLayer(MOCK_PUBLISHER_LAYER_ID,
57 MOCK_PUBLISHER_LAYER_SUBTYPE,
58 MOCK_PUBLISHER_LAYER_VERSION);
59 public static final byte[] PAYLOAD = new byte[]{1, 1, 2, 3, 5, 8, 13};
60
61 private HalHandler mHalHandler;
62 // Used to block until the HAL property is updated in HalHandler.onPropertySet.
63 private Semaphore mHalHandlerSemaphore;
64
65 @Override
66 protected synchronized void configureMockedHal() {
67 mHalHandler = new HalHandler();
68 addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
69 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
70 .setAccess(VehiclePropertyAccess.READ_WRITE)
71 .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
72 }
73
74 /**
75 * Creates a context with the resource vmsPublisherClients overridden. The overridden value
76 * contains the name of the test service defined also in this test package.
77 */
78 @Override
79 protected Context getCarServiceContext() throws PackageManager.NameNotFoundException {
80 Context context = getContext()
81 .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
82 Resources resources = new Resources(context.getAssets(),
83 context.getResources().getDisplayMetrics(),
84 context.getResources().getConfiguration()) {
85 @Override
86 public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
87 if (id == R.array.vmsPublisherClients) {
88 return new String[]{"com.android.car.test/.SimpleVmsPublisherClientService"};
89 }
90 return super.getStringArray(id);
91 }
92 };
93 ContextWrapper wrapper = new ContextWrapper(context) {
94 @Override
95 public Resources getResources() {
96 return resources;
97 }
98 };
99 return wrapper;
100 }
101
102 private VehiclePropValue getHalSubscriptionRequest() {
103 return VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
104 .addIntValue(VmsMessageType.SUBSCRIBE)
105 .addIntValue(MOCK_PUBLISHER_LAYER_ID)
106 .addIntValue(MOCK_PUBLISHER_LAYER_SUBTYPE)
107 .addIntValue(MOCK_PUBLISHER_LAYER_VERSION)
108 .build();
109 }
110
111 @Override
112 protected void setUp() throws Exception {
113 if (!VmsTestUtils.canRunTest(TAG)) return;
114 /**
115 * First init the semaphore, setUp will start a series of events that will ultimately
116 * update the HAL layer and release this semaphore.
117 */
118 mHalHandlerSemaphore = new Semaphore(0);
119 super.setUp();
120
121 // Inject a subscribe event which simulates the HAL is subscribed to the Mock Publisher.
122 MockedVehicleHal mHal = getMockedVehicleHal();
123 mHal.injectEvent(getHalSubscriptionRequest());
124 }
125
126 @Override
127 protected synchronized void tearDown() throws Exception {
128 if (!VmsTestUtils.canRunTest(TAG)) return;
129 super.tearDown();
130 }
131
132 /**
133 * The method setUp initializes all the Car services, including the VmsPublisherService.
134 * The VmsPublisherService will start and configure its list of clients. This list was
135 * overridden in the method getCarServiceContext.
136 * Therefore, only SimpleVmsPublisherClientService will be started.
137 * The service SimpleVmsPublisherClientService will publish one message, which is validated in
138 * this test.
139 */
140 public void testPublish() throws Exception {
141 if (!VmsTestUtils.canRunTest(TAG)) return;
142 //TODO: This test is using minial synchronisation between clients.
143 // If more complexity is added this may result in publisher
144 // publishing before the subscriber subscribed, in which case
145 // the semaphore will not be released.
146 assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
147 VehiclePropValue.RawValue rawValue = mHalHandler.getValue().value;
148 int messageType = rawValue.int32Values.get(VmsMessageWithLayerIntegerValuesIndex.MESSAGE_TYPE);
149 int layerId = rawValue.int32Values.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_TYPE);
150 int layerVersion = rawValue.int32Values.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_VERSION);
151 byte[] payload = new byte[rawValue.bytes.size()];
152 for (int i = 0; i < rawValue.bytes.size(); ++i) {
153 payload[i] = rawValue.bytes.get(i);
154 }
155 assertEquals(VmsMessageType.DATA, messageType);
156 assertEquals(MOCK_PUBLISHER_LAYER_ID, layerId);
157 assertEquals(MOCK_PUBLISHER_LAYER_VERSION, layerVersion);
158 assertTrue(Arrays.equals(PAYLOAD, payload));
159 }
160
161 private class HalHandler implements VehicleHalPropertyHandler {
162 private VehiclePropValue mValue;
163
164 @Override
165 public synchronized void onPropertySet(VehiclePropValue value) {
166 mValue = value;
167
168 // If this is the data message release the semaphone so the test can continue.
169 ArrayList<Integer> int32Values = value.value.int32Values;
170 if (int32Values.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE) ==
171 VmsMessageType.DATA) {
172 mHalHandlerSemaphore.release();
173 }
174 }
175
176 @Override
177 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
178 return mValue != null ? mValue : value;
179 }
180
181 @Override
182 public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
183 Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
184 }
185
186 @Override
187 public synchronized void onPropertyUnsubscribe(int property) {
188 Log.d(TAG, "onPropertyUnSubscribe property " + property);
189 }
190
191 public VehiclePropValue getValue() {
192 return mValue;
193 }
194 }
195} \ No newline at end of file
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java b/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java
deleted file mode 100644
index 1d14c570..00000000
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
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
17package com.android.car.test;
18
19import android.annotation.ArrayRes;
20import android.car.VehicleAreaType;
21import android.car.annotation.FutureFeature;
22import android.content.Context;
23import android.content.ContextWrapper;
24import android.content.pm.PackageManager;
25import android.content.res.Resources;
26import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
27import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
28import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
29import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
30import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
31import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
32import android.test.suitebuilder.annotation.MediumTest;
33
34import com.android.car.R;
35import com.android.car.vehiclehal.VehiclePropValueBuilder;
36import com.android.car.vehiclehal.test.MockedVehicleHal;
37import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
38
39import java.util.ArrayList;
40import java.util.concurrent.Semaphore;
41import java.util.concurrent.TimeUnit;
42
43@FutureFeature
44@MediumTest
45public class VmsPublisherPermissionsTest extends MockedCarTestBase {
46 private static final String TAG = "VmsPublisherTest";
47 private static final int MOCK_PUBLISHER_LAYER_ID = 0;
48 private static final int MOCK_PUBLISHER_LAYER_VERSION = 0;
49 private static final int MOCK_PUBLISHER_LAYER_FUSION_INT_VALUE = 0;
50
51 private HalHandler mHalHandler;
52 // Used to block until the HAL property is updated in HalHandler.onPropertySet.
53 private Semaphore mHalHandlerSemaphore;
54
55 @Override
56 protected synchronized void configureMockedHal() {
57 mHalHandler = new HalHandler();
58 addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
59 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
60 .setAccess(VehiclePropertyAccess.READ_WRITE)
61 .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
62 }
63
64 /**
65 * Creates a context with the resource vmsPublisherClients overridden. The overridden value
66 * contains the name of the test service defined also in this test package.
67 */
68 @Override
69 protected Context getCarServiceContext() throws PackageManager.NameNotFoundException {
70 Context context = getContext()
71 .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
72 Resources resources = new Resources(context.getAssets(),
73 context.getResources().getDisplayMetrics(),
74 context.getResources().getConfiguration()) {
75 @Override
76 public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
77 if (id == R.array.vmsPublisherClients) {
78 return new String[]{
79 "com.google.android.car.vms.publisher/"
80 + ".VmsPublisherClientSampleService"};
81 } else if (id == R.array.vmsSafePermissions) {
82 return new String[]{"android.permission.ACCESS_FINE_LOCATION"};
83 }
84 return super.getStringArray(id);
85 }
86 };
87 ContextWrapper wrapper = new ContextWrapper(context) {
88 @Override
89 public Resources getResources() {
90 return resources;
91 }
92 };
93 return wrapper;
94 }
95
96 private VehiclePropValue getHalSubscriptionRequest() {
97 return VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
98 .addIntValue(VmsMessageType.SUBSCRIBE)
99 .addIntValue(MOCK_PUBLISHER_LAYER_ID)
100 .addIntValue(MOCK_PUBLISHER_LAYER_VERSION)
101 .addIntValue(MOCK_PUBLISHER_LAYER_FUSION_INT_VALUE)
102 .build();
103 }
104
105 @Override
106 protected void setUp() throws Exception {
107 if (!VmsTestUtils.canRunTest(TAG)) return;
108 /**
109 * First init the semaphore, setUp will start a series of events that will ultimately
110 * update the HAL layer and release this semaphore.
111 */
112 mHalHandlerSemaphore = new Semaphore(0);
113 super.setUp();
114
115 // Inject a subscribe event which simulates the HAL is subscribed to the Sample Publisher.
116 MockedVehicleHal mHal = getMockedVehicleHal();
117 mHal.injectEvent(getHalSubscriptionRequest());
118 }
119
120 @Override
121 protected synchronized void tearDown() throws Exception {
122 if (!VmsTestUtils.canRunTest(TAG)) return;
123 super.tearDown();
124 }
125
126 /**
127 * The method setUp initializes all the Car services, including the VmsPublisherService.
128 * The VmsPublisherService will start and configure its list of clients. This list was
129 * overridden in the method getCarServiceContext.
130 * Therefore, only VmsPublisherClientSampleService will be started.
131 * The service VmsPublisherClientSampleService will publish one message, which is validated in
132 * this test.
133 */
134 public void testPermissions() throws Exception {
135 if (!VmsTestUtils.canRunTest(TAG)) return;
136 assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
137 // At this point the client initialization finished. Let's validate the permissions.
138 // The VMS service is only allowed to grant ACCESS_FINE_LOCATION but not CAMERA.
139 assertTrue(
140 getContext().getPackageManager().checkPermission(
141 "android.permission.ACCESS_FINE_LOCATION",
142 "com.google.android.car.vms.publisher")
143 == PackageManager.PERMISSION_GRANTED);
144 assertFalse(getContext().getPackageManager().checkPermission(
145 "android.permission.CAMERA", "com.google.android.car.vms.publisher")
146 == PackageManager.PERMISSION_GRANTED);
147 }
148
149 private class HalHandler implements VehicleHalPropertyHandler {
150 @Override
151 public synchronized void onPropertySet(VehiclePropValue value) {
152 // If this is the data message release the semaphore so the test can continue.
153 ArrayList<Integer> int32Values = value.value.int32Values;
154 if (int32Values.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE) ==
155 VmsMessageType.DATA) {
156 mHalHandlerSemaphore.release();
157 }
158 }
159 }
160}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java b/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
deleted file mode 100644
index 5b387d2e..00000000
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
+++ /dev/null
@@ -1,238 +0,0 @@
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
17package com.android.car.test;
18
19import android.annotation.ArrayRes;
20import android.car.Car;
21import android.car.VehicleAreaType;
22import android.car.annotation.FutureFeature;
23import android.car.vms.VmsAssociatedLayer;
24import android.car.vms.VmsLayer;
25import android.car.vms.VmsSubscriberManager;
26import android.content.Context;
27import android.content.ContextWrapper;
28import android.content.pm.PackageManager;
29import android.content.res.Resources;
30import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
31import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
32import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
33import android.test.suitebuilder.annotation.MediumTest;
34
35import com.android.car.vehiclehal.test.MockedVehicleHal;
36
37import java.util.ArrayList;
38import java.util.Arrays;
39import java.util.HashSet;
40import java.util.List;
41import java.util.concurrent.Semaphore;
42import java.util.concurrent.TimeUnit;
43
44@FutureFeature
45@MediumTest
46public class VmsPublisherSubscriberTest extends MockedCarTestBase {
47 private static final int LAYER_ID = 88;
48 private static final int LAYER_VERSION = 19;
49 private static final int LAYER_SUBTYPE = 55;
50 private static final String TAG = "VmsPubSubTest";
51
52 // The expected publisher ID is 0 since it the expected assigned ID from the VMS core.
53 public static final int EXPECTED_PUBLISHER_ID = 0;
54 public static final VmsLayer LAYER = new VmsLayer(LAYER_ID, LAYER_SUBTYPE, LAYER_VERSION);
55 public static final VmsAssociatedLayer ASSOCIATED_LAYER =
56 new VmsAssociatedLayer(LAYER, new HashSet<>(Arrays.asList(EXPECTED_PUBLISHER_ID)));
57 public static final byte[] PAYLOAD = new byte[]{2, 3, 5, 7, 11, 13, 17};
58
59 private static final List<VmsAssociatedLayer> AVAILABLE_ASSOCIATED_LAYERS =
60 new ArrayList<>(Arrays.asList(ASSOCIATED_LAYER));
61
62
63 private static final int SUBSCRIBED_LAYER_ID = 89;
64 public static final VmsLayer SUBSCRIBED_LAYER =
65 new VmsLayer(SUBSCRIBED_LAYER_ID, LAYER_SUBTYPE, LAYER_VERSION);
66 public static final VmsAssociatedLayer ASSOCIATED_SUBSCRIBED_LAYER =
67 new VmsAssociatedLayer(SUBSCRIBED_LAYER, new HashSet<>(Arrays.asList(EXPECTED_PUBLISHER_ID)));
68 private static final List<VmsAssociatedLayer> AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER =
69 new ArrayList<>(Arrays.asList(ASSOCIATED_LAYER, ASSOCIATED_SUBSCRIBED_LAYER));
70
71
72 private HalHandler mHalHandler;
73 // Used to block until a value is propagated to the TestClientCallback.onVmsMessageReceived.
74 private Semaphore mSubscriberSemaphore;
75 private Semaphore mAvailabilitySemaphore;
76
77 @Override
78 protected synchronized void configureMockedHal() {
79 mHalHandler = new HalHandler();
80 addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
81 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
82 .setAccess(VehiclePropertyAccess.READ_WRITE)
83 .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
84 }
85
86 /**
87 * Creates a context with the resource vmsPublisherClients overridden. The overridden value
88 * contains the name of the test service defined also in this test package.
89 */
90 @Override
91 protected Context getCarServiceContext() throws PackageManager.NameNotFoundException {
92 Context context = getContext()
93 .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
94 Resources resources = new Resources(context.getAssets(),
95 context.getResources().getDisplayMetrics(),
96 context.getResources().getConfiguration()) {
97 @Override
98 public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
99 if (id == com.android.car.R.array.vmsPublisherClients) {
100 return new String[]{"com.android.car.test/.VmsPublisherClientMockService"};
101 }
102 return super.getStringArray(id);
103 }
104 };
105 ContextWrapper wrapper = new ContextWrapper(context) {
106 @Override
107 public Resources getResources() {
108 return resources;
109 }
110 };
111 return wrapper;
112 }
113
114 @Override
115 protected void setUp() throws Exception {
116 if (!VmsTestUtils.canRunTest(TAG)) return;
117 super.setUp();
118 mSubscriberSemaphore = new Semaphore(0);
119 mAvailabilitySemaphore = new Semaphore(0);
120 }
121
122 @Override
123 protected synchronized void tearDown() throws Exception {
124 if (!VmsTestUtils.canRunTest(TAG)) return;
125 super.tearDown();
126 }
127
128 /**
129 * The method setUp initializes all the Car services, including the VmsPublisherService.
130 * The VmsPublisherService will start and configure its list of clients. This list was
131 * overridden in the method getCarServiceContext. Therefore, only VmsPublisherClientMockService
132 * will be started. This test method subscribes to a layer and triggers
133 * VmsPublisherClientMockService.onVmsSubscriptionChange. In turn, the mock service will publish
134 * a message, which is validated in this test.
135 */
136 public void testPublisherToSubscriber() throws Exception {
137 if (!VmsTestUtils.canRunTest(TAG)) return;
138 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
139 Car.VMS_SUBSCRIBER_SERVICE);
140 TestClientCallback clientCallback = new TestClientCallback();
141 vmsSubscriberManager.registerClientCallback(clientCallback);
142 vmsSubscriberManager.subscribe(LAYER);
143
144 assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
145 assertEquals(LAYER, clientCallback.getLayer());
146 assertTrue(Arrays.equals(PAYLOAD, clientCallback.getPayload()));
147 }
148
149 /**
150 * The Mock service will get a publisher ID by sending its information when it will get
151 * ServiceReady as well as on SubscriptionChange. Since clients are not notified when
152 * publishers are assigned IDs, this test waits until the availability is changed which indicates
153 * that the Mock service has gotten its ServiceReady and publisherId.
154 */
155 public void testPublisherInfo() throws Exception {
156 if (!VmsTestUtils.canRunTest(TAG)) return;
157 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
158 Car.VMS_SUBSCRIBER_SERVICE);
159 // Subscribe to layer as a way to make sure the mock client completed setting the information.
160 TestClientCallback clientCallback = new TestClientCallback();
161 vmsSubscriberManager.registerClientCallback(clientCallback);
162 vmsSubscriberManager.subscribe(LAYER);
163
164 assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
165
166 byte[] info = vmsSubscriberManager.getPublisherInfo(EXPECTED_PUBLISHER_ID);
167 assertTrue(Arrays.equals(PAYLOAD, info));
168 }
169
170 /**
171 * The Mock service offers all the subscribed layers as available layers.
172 * In this test the client subscribes to a layer and verifies that it gets the
173 * notification that it is available.
174 */
175 public void testAvailabilityWithSubscription() throws Exception {
176 if (!VmsTestUtils.canRunTest(TAG)) return;
177 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
178 Car.VMS_SUBSCRIBER_SERVICE);
179 TestClientCallback clientCallback = new TestClientCallback();
180 vmsSubscriberManager.registerClientCallback(clientCallback);
181 vmsSubscriberManager.subscribe(SUBSCRIBED_LAYER);
182
183 assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
184 assertEquals(AVAILABLE_ASSOCIATED_LAYERS_WITH_SUBSCRIBED_LAYER, clientCallback.getAvailalbeLayers());
185 }
186
187 /**
188 * The Mock service offers all the subscribed layers as available layers, so in this
189 * test the client subscribes to a layer and verifies that it gets the notification that it
190 * is available.
191 */
192 public void testAvailabilityWithoutSubscription() throws Exception {
193 if (!VmsTestUtils.canRunTest(TAG)) return;
194 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
195 Car.VMS_SUBSCRIBER_SERVICE);
196 TestClientCallback clientCallback = new TestClientCallback();
197 vmsSubscriberManager.registerClientCallback(clientCallback);
198
199 assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
200 assertEquals(AVAILABLE_ASSOCIATED_LAYERS, clientCallback.getAvailalbeLayers());
201 }
202
203 private class HalHandler implements MockedVehicleHal.VehicleHalPropertyHandler {
204 }
205
206 private class TestClientCallback implements VmsSubscriberManager.VmsSubscriberClientCallback {
207 private VmsLayer mLayer;
208 private byte[] mPayload;
209 private List<VmsLayer> mAvailableLayers;
210
211 @Override
212 public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
213 assertEquals(LAYER, layer);
214 assertTrue(Arrays.equals(PAYLOAD, payload));
215 mLayer = layer;
216 mPayload = payload;
217 mSubscriberSemaphore.release();
218 }
219
220 @Override
221 public void onLayersAvailabilityChanged(List<VmsLayer> availableLayers) {
222 mAvailableLayers = availableLayers;
223 mAvailabilitySemaphore.release();
224 }
225
226 public VmsLayer getLayer() {
227 return mLayer;
228 }
229
230 public byte[] getPayload() {
231 return mPayload;
232 }
233
234 public List<VmsLayer> getAvailalbeLayers() {
235 return mAvailableLayers;
236 }
237 }
238}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java b/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
deleted file mode 100644
index 9e9a5d08..00000000
--- a/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
+++ /dev/null
@@ -1,614 +0,0 @@
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
17package com.android.car.test;
18
19import static org.junit.Assume.assumeTrue;
20
21import android.car.Car;
22import android.car.VehicleAreaType;
23import android.car.annotation.FutureFeature;
24import android.car.vms.VmsAssociatedLayer;
25import android.car.vms.VmsLayer;
26import android.car.vms.VmsSubscriberManager;
27import android.car.vms.VmsSubscriberManager.VmsSubscriberClientCallback;
28import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
29import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
30import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
31import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
32import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
33import android.os.SystemClock;
34import android.test.suitebuilder.annotation.MediumTest;
35import android.util.Log;
36import com.android.car.vehiclehal.VehiclePropValueBuilder;
37import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
38
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.HashSet;
42import java.util.List;
43import java.util.Set;
44import java.util.concurrent.Semaphore;
45import java.util.concurrent.TimeUnit;
46
47@FutureFeature
48@MediumTest
49public class VmsSubscriberManagerTest extends MockedCarTestBase {
50 private static final String TAG = "VmsSubscriberManagerTest";
51 private static final int PUBLISHER_ID = 17;
52 private static final int WRONG_PUBLISHER_ID = 26;
53 private static final Set<Integer> PUBLISHERS_LIST = new HashSet<Integer>(Arrays.asList(PUBLISHER_ID));
54
55 private static final int SUBSCRIPTION_LAYER_ID = 2;
56 private static final int SUBSCRIPTION_LAYER_VERSION = 3;
57 private static final int MOCK_PUBLISHER_LAYER_SUBTYPE = 444;
58 private static final VmsLayer SUBSCRIPTION_LAYER = new VmsLayer(SUBSCRIPTION_LAYER_ID,
59 MOCK_PUBLISHER_LAYER_SUBTYPE,
60 SUBSCRIPTION_LAYER_VERSION);
61 private static final VmsAssociatedLayer SUBSCRIPTION_ASSOCIATED_LAYER =
62 new VmsAssociatedLayer(SUBSCRIPTION_LAYER, PUBLISHERS_LIST);
63
64 private static final int SUBSCRIPTION_DEPENDANT_LAYER_ID_1 = 4;
65 private static final int SUBSCRIPTION_DEPENDANT_LAYER_VERSION_1 = 5;
66 private static final VmsLayer SUBSCRIPTION_DEPENDANT_LAYER_1 =
67 new VmsLayer(SUBSCRIPTION_DEPENDANT_LAYER_ID_1,
68 MOCK_PUBLISHER_LAYER_SUBTYPE,
69 SUBSCRIPTION_DEPENDANT_LAYER_VERSION_1);
70
71 private static final VmsAssociatedLayer SUBSCRIPTION_DEPENDANT_ASSOCIATED_LAYER_1 =
72 new VmsAssociatedLayer(SUBSCRIPTION_DEPENDANT_LAYER_1, PUBLISHERS_LIST);
73
74 private static final int SUBSCRIPTION_DEPENDANT_LAYER_ID_2 = 6;
75 private static final int SUBSCRIPTION_DEPENDANT_LAYER_VERSION_2 = 7;
76 private static final VmsLayer SUBSCRIPTION_DEPENDANT_LAYER_2 =
77 new VmsLayer(SUBSCRIPTION_DEPENDANT_LAYER_ID_2,
78 MOCK_PUBLISHER_LAYER_SUBTYPE,
79 SUBSCRIPTION_DEPENDANT_LAYER_VERSION_2);
80
81 private static final VmsAssociatedLayer SUBSCRIPTION_DEPENDANT_ASSOCIATED_LAYER_2 =
82 new VmsAssociatedLayer(SUBSCRIPTION_DEPENDANT_LAYER_2, PUBLISHERS_LIST);
83
84 private static final int SUBSCRIPTION_UNSUPPORTED_LAYER_ID = 100;
85 private static final int SUBSCRIPTION_UNSUPPORTED_LAYER_VERSION = 200;
86
87
88 private HalHandler mHalHandler;
89 // Used to block until the HAL property is updated in HalHandler.onPropertySet.
90 private Semaphore mHalHandlerSemaphore;
91 // Used to block until a value is propagated to the TestClientCallback.onVmsMessageReceived.
92 private Semaphore mSubscriberSemaphore;
93
94 @Override
95 protected synchronized void configureMockedHal() {
96 mHalHandler = new HalHandler();
97 addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
98 .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
99 .setAccess(VehiclePropertyAccess.READ_WRITE)
100 .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
101 }
102
103 @Override
104 protected void setUp() throws Exception {
105 if (!VmsTestUtils.canRunTest(TAG)) return;
106 super.setUp();
107 mSubscriberSemaphore = new Semaphore(0);
108 mHalHandlerSemaphore = new Semaphore(0);
109 }
110
111 @Override
112 protected synchronized void tearDown() throws Exception {
113 if (!VmsTestUtils.canRunTest(TAG)) return;
114 super.tearDown();
115 }
116
117 // Test injecting a value in the HAL and verifying it propagates to a subscriber.
118 public void testSubscribe() throws Exception {
119 if (!VmsTestUtils.canRunTest(TAG)) return;
120 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
121 Car.VMS_SUBSCRIBER_SERVICE);
122 TestClientCallback clientCallback = new TestClientCallback();
123 vmsSubscriberManager.registerClientCallback(clientCallback);
124 vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
125
126 // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
127 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
128 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
129 .setTimestamp(SystemClock.elapsedRealtimeNanos())
130 .build();
131 v.value.int32Values.add(VmsMessageType.DATA); // MessageType
132 v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
133 v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUBTYPE);
134 v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
135 v.value.int32Values.add(PUBLISHER_ID);
136 v.value.bytes.add((byte) 0xa);
137 v.value.bytes.add((byte) 0xb);
138 assertEquals(0, mSubscriberSemaphore.availablePermits());
139
140 getMockedVehicleHal().injectEvent(v);
141 assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
142 assertEquals(SUBSCRIPTION_LAYER, clientCallback.getLayer());
143 byte[] expectedPayload = {(byte) 0xa, (byte) 0xb};
144 assertTrue(Arrays.equals(expectedPayload, clientCallback.getPayload()));
145 }
146
147
148 // Test injecting a value in the HAL and verifying it propagates to a subscriber.
149 public void testSubscribeToPublisher() throws Exception {
150 if (!VmsTestUtils.canRunTest(TAG)) return;
151 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
152 Car.VMS_SUBSCRIBER_SERVICE);
153 TestClientCallback clientCallback = new TestClientCallback();
154 vmsSubscriberManager.registerClientCallback(clientCallback);
155 vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
156
157 // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
158 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
159 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
160 .setTimestamp(SystemClock.elapsedRealtimeNanos())
161 .build();
162 v.value.int32Values.add(VmsMessageType.DATA); // MessageType
163 v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
164 v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUBTYPE);
165 v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
166 v.value.int32Values.add(WRONG_PUBLISHER_ID);
167 v.value.bytes.add((byte) 0xa);
168 v.value.bytes.add((byte) 0xb);
169 assertEquals(0, mSubscriberSemaphore.availablePermits());
170
171 getMockedVehicleHal().injectEvent(v);
172
173 assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
174 }
175
176 // Test injecting a value in the HAL and verifying it propagates to a subscriber.
177 public void testSubscribeFromPublisher() throws Exception {
178 if (!VmsTestUtils.canRunTest(TAG)) return;
179 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
180 Car.VMS_SUBSCRIBER_SERVICE);
181 TestClientCallback clientCallback = new TestClientCallback();
182 vmsSubscriberManager.registerClientCallback(clientCallback);
183 vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
184
185 // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
186 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
187 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
188 .setTimestamp(SystemClock.elapsedRealtimeNanos())
189 .build();
190 v.value.int32Values.add(VmsMessageType.DATA); // MessageType
191 v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
192 v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUBTYPE); //<-
193 v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
194 v.value.int32Values.add(PUBLISHER_ID);
195 v.value.bytes.add((byte) 0xa);
196 v.value.bytes.add((byte) 0xb);
197 assertEquals(0, mSubscriberSemaphore.availablePermits());
198
199 getMockedVehicleHal().injectEvent(v);
200 assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
201 assertEquals(SUBSCRIPTION_LAYER, clientCallback.getLayer());
202 byte[] expectedPayload = {(byte) 0xa, (byte) 0xb};
203 assertTrue(Arrays.equals(expectedPayload, clientCallback.getPayload()));
204 }
205
206 // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
207 public void testUnsubscribe() throws Exception {
208 if (!VmsTestUtils.canRunTest(TAG)) return;
209 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
210 Car.VMS_SUBSCRIBER_SERVICE);
211 TestClientCallback clientCallback = new TestClientCallback();
212 vmsSubscriberManager.registerClientCallback(clientCallback);
213 vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
214 vmsSubscriberManager.unsubscribe(SUBSCRIPTION_LAYER);
215
216 // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
217 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
218 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
219 .setTimestamp(SystemClock.elapsedRealtimeNanos())
220 .build();
221 v.value.int32Values.add(VmsMessageType.DATA); // MessageType
222 v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
223 v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUBTYPE);
224 v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
225 v.value.int32Values.add(PUBLISHER_ID);
226 v.value.bytes.add((byte) 0xa);
227 v.value.bytes.add((byte) 0xb);
228 assertEquals(0, mSubscriberSemaphore.availablePermits());
229
230 getMockedVehicleHal().injectEvent(v);
231 assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
232 }
233
234 // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
235 public void testSubscribeFromWrongPublisher() throws Exception {
236 if (!VmsTestUtils.canRunTest(TAG)) return;
237 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
238 Car.VMS_SUBSCRIBER_SERVICE);
239 TestClientCallback clientCallback = new TestClientCallback();
240 vmsSubscriberManager.registerClientCallback(clientCallback);
241 vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
242
243 // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
244 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
245 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
246 .setTimestamp(SystemClock.elapsedRealtimeNanos())
247 .build();
248 v.value.int32Values.add(VmsMessageType.DATA); // MessageType
249 v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
250 v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUBTYPE);
251 v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
252 v.value.int32Values.add(WRONG_PUBLISHER_ID);
253 v.value.bytes.add((byte) 0xa);
254 v.value.bytes.add((byte) 0xb);
255 assertEquals(0, mSubscriberSemaphore.availablePermits());
256
257 getMockedVehicleHal().injectEvent(v);
258 assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
259 }
260
261 // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
262 public void testUnsubscribeFromPublisher() throws Exception {
263 if (!VmsTestUtils.canRunTest(TAG)) return;
264 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
265 Car.VMS_SUBSCRIBER_SERVICE);
266 TestClientCallback clientCallback = new TestClientCallback();
267 vmsSubscriberManager.registerClientCallback(clientCallback);
268 vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
269 vmsSubscriberManager.unsubscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
270
271 // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
272 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
273 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
274 .setTimestamp(SystemClock.elapsedRealtimeNanos())
275 .build();
276 v.value.int32Values.add(VmsMessageType.DATA); // MessageType
277 v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
278 v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUBTYPE);
279 v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
280 v.value.int32Values.add(PUBLISHER_ID);
281 v.value.bytes.add((byte) 0xa);
282 v.value.bytes.add((byte) 0xb);
283 assertEquals(0, mSubscriberSemaphore.availablePermits());
284
285 getMockedVehicleHal().injectEvent(v);
286 assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
287 }
288
289
290 // Test injecting a value in the HAL and verifying it propagates to a subscriber.
291 public void testSubscribeAll() throws Exception {
292 if (!VmsTestUtils.canRunTest(TAG)) return;
293 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
294 Car.VMS_SUBSCRIBER_SERVICE);
295 TestClientCallback clientCallback = new TestClientCallback();
296 vmsSubscriberManager.registerClientCallback(clientCallback);
297 vmsSubscriberManager.startMonitoring();
298
299 // Inject a value and wait for its callback in TestClientCallback.onVmsMessageReceived.
300 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
301 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
302 .setTimestamp(SystemClock.elapsedRealtimeNanos())
303 .build();
304 v.value.int32Values.add(VmsMessageType.DATA); // MessageType
305 v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
306 v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUBTYPE);
307 v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
308 v.value.int32Values.add(PUBLISHER_ID);
309 v.value.bytes.add((byte) 0xa);
310 v.value.bytes.add((byte) 0xb);
311 assertEquals(0, mSubscriberSemaphore.availablePermits());
312
313 getMockedVehicleHal().injectEvent(v);
314 assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
315 assertEquals(SUBSCRIPTION_LAYER, clientCallback.getLayer());
316 byte[] expectedPayload = {(byte) 0xa, (byte) 0xb};
317 assertTrue(Arrays.equals(expectedPayload, clientCallback.getPayload()));
318 }
319
320 // Test injecting a value in the HAL and verifying it propagates to a subscriber.
321 public void testSimpleAvailableLayers() throws Exception {
322 if (!VmsTestUtils.canRunTest(TAG)) return;
323 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
324 Car.VMS_SUBSCRIBER_SERVICE);
325 TestClientCallback clientCallback = new TestClientCallback();
326 vmsSubscriberManager.registerClientCallback(clientCallback);
327
328 // Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
329 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
330 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
331 .setTimestamp(SystemClock.elapsedRealtimeNanos())
332 .build();
333 /*
334 Offering:
335 Layer | Dependency
336 ===============================
337 (2, 3, 444), [17] | {}
338
339 Expected availability:
340 {(2, 3, 444 [17])}
341 */
342 v.value.int32Values.addAll(
343 Arrays.asList(
344 VmsMessageType.OFFERING, // MessageType
345 PUBLISHER_ID,
346 1, // Number of offered layers
347
348 SUBSCRIPTION_LAYER_ID,
349 MOCK_PUBLISHER_LAYER_SUBTYPE,
350 SUBSCRIPTION_LAYER_VERSION,
351 0 // number of dependencies for layer
352 )
353 );
354
355 assertEquals(0, mSubscriberSemaphore.availablePermits());
356
357 getMockedVehicleHal().injectEvent(v);
358 assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
359 List<VmsAssociatedLayer> expectedAvailableLayers =
360 new ArrayList<>(Arrays.asList(SUBSCRIPTION_ASSOCIATED_LAYER));
361 assertTrue(expectedAvailableLayers.containsAll(clientCallback.getAvailableLayers()));
362 assertEquals(expectedAvailableLayers.size(), clientCallback.getAvailableLayers().size());
363 }
364
365 // Test injecting a value in the HAL and verifying it propagates to a subscriber after it has
366 // subscribed to a layer.
367 public void testSimpleAvailableLayersAfterSubscription() throws Exception {
368 if (!VmsTestUtils.canRunTest(TAG)) return;
369 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
370 Car.VMS_SUBSCRIBER_SERVICE);
371 TestClientCallback clientCallback = new TestClientCallback();
372 vmsSubscriberManager.registerClientCallback(clientCallback);
373 vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
374
375 // Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
376 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
377 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
378 .setTimestamp(SystemClock.elapsedRealtimeNanos())
379 .build();
380 /*
381 Offering:
382 Layer | Dependency
383 ===============================
384 (2, 3, 444), [17] | {}
385
386 Expected availability:
387 {(2, 3, 444 [17])}
388 */
389 v.value.int32Values.addAll(
390 Arrays.asList(
391 VmsMessageType.OFFERING, // MessageType
392 PUBLISHER_ID,
393 1, // Number of offered layers
394
395 SUBSCRIPTION_LAYER_ID,
396 MOCK_PUBLISHER_LAYER_SUBTYPE,
397 SUBSCRIPTION_LAYER_VERSION,
398 0 // number of dependencies for layer
399 )
400 );
401
402 assertEquals(0, mSubscriberSemaphore.availablePermits());
403
404 getMockedVehicleHal().injectEvent(v);
405 assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
406 List<VmsAssociatedLayer> expectedAvailableLayers =
407 new ArrayList<>(Arrays.asList(SUBSCRIPTION_ASSOCIATED_LAYER));
408 assertTrue(expectedAvailableLayers.containsAll(clientCallback.getAvailableLayers()));
409 assertEquals(expectedAvailableLayers.size(), clientCallback.getAvailableLayers().size());
410 }
411
412 // Test injecting a value in the HAL and verifying it does not propagates to a subscriber after
413 // it has unregistered its callback.
414 public void testSimpleAvailableLayersAfterUnregister() throws Exception {
415 if (!VmsTestUtils.canRunTest(TAG)) return;
416 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
417 Car.VMS_SUBSCRIBER_SERVICE);
418 TestClientCallback clientCallback = new TestClientCallback();
419 vmsSubscriberManager.registerClientCallback(clientCallback);
420 vmsSubscriberManager.unregisterClientCallback();
421
422
423 // Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
424 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
425 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
426 .setTimestamp(SystemClock.elapsedRealtimeNanos())
427 .build();
428 /*
429 Offering:
430 Layer | Dependency
431 ===============================
432 (2, 3, 444), [17] | {}
433
434 Expected availability:
435 {(2, 3, 444 [17])}
436 */
437 v.value.int32Values.addAll(
438 Arrays.asList(
439 VmsMessageType.OFFERING, // MessageType
440 PUBLISHER_ID,
441 1, // Number of offered layers
442
443 SUBSCRIPTION_LAYER_ID,
444 SUBSCRIPTION_LAYER_VERSION,
445 MOCK_PUBLISHER_LAYER_SUBTYPE,
446 0 // number of dependencies for layer
447 )
448 );
449
450 assertEquals(0, mSubscriberSemaphore.availablePermits());
451 getMockedVehicleHal().injectEvent(v);
452 assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
453 }
454
455 // Test injecting a value in the HAL and verifying it does not propagates to a subscriber after
456 // it has unregistered its callback.
457 public void testSomething() throws Exception {
458 if (!VmsTestUtils.canRunTest(TAG)) return;
459 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
460 Car.VMS_SUBSCRIBER_SERVICE);
461 TestClientCallback clientCallback = new TestClientCallback();
462 vmsSubscriberManager.registerClientCallback(clientCallback);
463 vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
464 try {
465 vmsSubscriberManager.unregisterClientCallback();
466 } catch (IllegalArgumentException e) {
467 return;
468 }
469 fail();
470 }
471
472
473 // Test injecting a value in the HAL and verifying it propagates to a subscriber.
474 public void testComplexAvailableLayers() throws Exception {
475 if (!VmsTestUtils.canRunTest(TAG)) return;
476 VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
477 Car.VMS_SUBSCRIBER_SERVICE);
478 TestClientCallback clientCallback = new TestClientCallback();
479 vmsSubscriberManager.registerClientCallback(clientCallback);
480
481 // Inject a value and wait for its callback in TestClientCallback.onLayersAvailabilityChanged.
482 VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
483 .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
484 .setTimestamp(SystemClock.elapsedRealtimeNanos())
485 .build();
486 /*
487 Offering:
488 Layer | Dependency
489 ====================
490 (2, 3, 444), [17] | {}
491 (4, 5, 444), [17] | {(2, 3)}
492 (6, 7, 444), [17] | {(2, 3), (4, 5)}
493 (6, 7, 444), [17] | {(100, 200)}
494
495 Expected availability:
496 {(2, 3, 444 [17]), (4, 5, 444 [17]), (6, 7, 444 [17])}
497 */
498
499 v.value.int32Values.addAll(
500 Arrays.asList(
501 VmsMessageType.OFFERING, // MessageType
502 PUBLISHER_ID,
503 4, // Number of offered layers
504
505 SUBSCRIPTION_LAYER_ID,
506 MOCK_PUBLISHER_LAYER_SUBTYPE,
507 SUBSCRIPTION_LAYER_VERSION,
508 0, // number of dependencies for layer
509
510 SUBSCRIPTION_DEPENDANT_LAYER_ID_1,
511 MOCK_PUBLISHER_LAYER_SUBTYPE,
512 SUBSCRIPTION_DEPENDANT_LAYER_VERSION_1,
513 1, // number of dependencies for layer
514 SUBSCRIPTION_LAYER_ID,
515 MOCK_PUBLISHER_LAYER_SUBTYPE,
516 SUBSCRIPTION_LAYER_VERSION,
517
518 SUBSCRIPTION_DEPENDANT_LAYER_ID_2,
519 MOCK_PUBLISHER_LAYER_SUBTYPE,
520 SUBSCRIPTION_DEPENDANT_LAYER_VERSION_2,
521 2, // number of dependencies for layer
522 SUBSCRIPTION_LAYER_ID,
523 MOCK_PUBLISHER_LAYER_SUBTYPE,
524 SUBSCRIPTION_LAYER_VERSION,
525 SUBSCRIPTION_DEPENDANT_LAYER_ID_1,
526 MOCK_PUBLISHER_LAYER_SUBTYPE,
527 SUBSCRIPTION_DEPENDANT_LAYER_VERSION_1,
528
529 SUBSCRIPTION_DEPENDANT_LAYER_ID_2,
530 MOCK_PUBLISHER_LAYER_SUBTYPE,
531 SUBSCRIPTION_DEPENDANT_LAYER_VERSION_2,
532 1, // number of dependencies for layer
533 SUBSCRIPTION_UNSUPPORTED_LAYER_ID,
534 MOCK_PUBLISHER_LAYER_SUBTYPE,
535 SUBSCRIPTION_UNSUPPORTED_LAYER_VERSION
536 )
537 );
538
539 assertEquals(0, mSubscriberSemaphore.availablePermits());
540
541 List<VmsAssociatedLayer> expectedAvailableLayers =
542 new ArrayList<>(Arrays.asList(
543 SUBSCRIPTION_ASSOCIATED_LAYER,
544 SUBSCRIPTION_DEPENDANT_ASSOCIATED_LAYER_1,
545 SUBSCRIPTION_DEPENDANT_ASSOCIATED_LAYER_2
546 ));
547 getMockedVehicleHal().injectEvent(v);
548 assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
549 assertTrue(expectedAvailableLayers.containsAll(clientCallback.getAvailableLayers()));
550 assertEquals(expectedAvailableLayers.size(), clientCallback.getAvailableLayers().size());
551 }
552
553 private class HalHandler implements VehicleHalPropertyHandler {
554 private VehiclePropValue mValue;
555
556 @Override
557 public synchronized void onPropertySet(VehiclePropValue value) {
558 mValue = value;
559 mHalHandlerSemaphore.release();
560 }
561
562 @Override
563 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
564 return mValue != null ? mValue : value;
565 }
566
567 @Override
568 public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
569 Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
570 }
571
572 @Override
573 public synchronized void onPropertyUnsubscribe(int property) {
574 Log.d(TAG, "onPropertyUnSubscribe property " + property);
575 }
576
577 public VehiclePropValue getValue() {
578 return mValue;
579 }
580 }
581
582 private class TestClientCallback implements VmsSubscriberClientCallback {
583 private VmsLayer mLayer;
584 private byte[] mPayload;
585 private List<VmsLayer> mAvailableLayers = new ArrayList<>();
586
587 @Override
588 public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
589 Log.d(TAG, "onVmsMessageReceived: layer: " + layer + " Payload: " + payload);
590 mLayer = layer;
591 mPayload = payload;
592 mSubscriberSemaphore.release();
593 }
594
595 @Override
596 public void onLayersAvailabilityChanged(List<VmsLayer> availableLayers) {
597 Log.d(TAG, "onLayersAvailabilityChanged: Layers: " + availableLayers);
598 mAvailableLayers.addAll(availableLayers);
599 mSubscriberSemaphore.release();
600 }
601
602 public VmsLayer getLayer() {
603 return mLayer;
604 }
605
606 public byte[] getPayload() {
607 return mPayload;
608 }
609
610 public List<VmsLayer> getAvailableLayers() {
611 return mAvailableLayers;
612 }
613 }
614}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java b/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java
deleted file mode 100644
index 2f3af52a..00000000
--- a/tests/carservice_test/src/com/android/car/test/VmsTestUtils.java
+++ /dev/null
@@ -1,16 +0,0 @@
1package com.android.car.test;
2
3import android.car.annotation.FutureFeature;
4import android.util.Log;
5
6import com.android.car.internal.FeatureConfiguration;
7
8@FutureFeature
9public class VmsTestUtils {
10 public static boolean canRunTest(String tag) {
11 if (!FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE) {
12 Log.i(tag, "Skipping test because ENABLE_VEHICLE_MAP_SERVICE = false");
13 }
14 return FeatureConfiguration.ENABLE_VEHICLE_MAP_SERVICE;
15 }
16}
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsLayersAvailabilityTest.java b/tests/carservice_unit_test/src/com/android/car/VmsLayersAvailabilityTest.java
deleted file mode 100644
index 4a09d4f8..00000000
--- a/tests/carservice_unit_test/src/com/android/car/VmsLayersAvailabilityTest.java
+++ /dev/null
@@ -1,266 +0,0 @@
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
17package com.android.car;
18
19import android.car.vms.VmsAssociatedLayer;
20import android.car.vms.VmsLayer;
21import android.car.vms.VmsLayerDependency;
22import android.car.vms.VmsLayersOffering;
23import android.test.AndroidTestCase;
24import android.test.suitebuilder.annotation.SmallTest;
25
26import java.util.Arrays;
27import java.util.Collections;
28import java.util.HashSet;
29import java.util.Set;
30
31@SmallTest
32public class VmsLayersAvailabilityTest extends AndroidTestCase {
33
34 private static final VmsLayer LAYER_X = new VmsLayer(1, 1, 2);
35 private static final VmsLayer LAYER_Y = new VmsLayer(3, 2, 4);
36 private static final VmsLayer LAYER_Z = new VmsLayer(5, 3, 6);
37
38 private static final int PUBLISHER_ID_1 = 19;
39 private static final int PUBLISHER_ID_2 = 28;
40
41 private static final Set<Integer> PUBLISHERS_1 = new HashSet<>(Arrays.asList(PUBLISHER_ID_1));
42 private static final Set<Integer> PUBLISHERS_2 = new HashSet<>(Arrays.asList(PUBLISHER_ID_2));
43 private static final Set<Integer> PUBLISHERS_1_AND_2 =
44 new HashSet<>(Arrays.asList(PUBLISHER_ID_1, PUBLISHER_ID_2));
45
46 private static final VmsLayerDependency X_DEPENDS_ON_Y =
47 new VmsLayerDependency(LAYER_X, new HashSet<VmsLayer>(Arrays.asList(LAYER_Y)));
48
49 private static final VmsLayerDependency X_DEPENDS_ON_Z =
50 new VmsLayerDependency(LAYER_X, new HashSet<VmsLayer>(Arrays.asList(LAYER_Z)));
51
52 private static final VmsLayerDependency Y_DEPENDS_ON_Z =
53 new VmsLayerDependency(LAYER_Y, new HashSet<VmsLayer>(Arrays.asList(LAYER_Z)));
54
55 private static final VmsLayerDependency Y_DEPENDS_ON_X =
56 new VmsLayerDependency(LAYER_Y, new HashSet<VmsLayer>(Arrays.asList(LAYER_X)));
57
58 private static final VmsLayerDependency Z_DEPENDS_ON_X =
59 new VmsLayerDependency(LAYER_Z, new HashSet<VmsLayer>(Arrays.asList(LAYER_X)));
60
61 private static final VmsLayerDependency Z_DEPENDS_ON_NOTHING =
62 new VmsLayerDependency(LAYER_Z);
63
64 private static final VmsLayerDependency X_DEPENDS_ON_SELF =
65 new VmsLayerDependency(LAYER_X, new HashSet<VmsLayer>(Arrays.asList(LAYER_X)));
66
67 private Set<VmsLayersOffering> mOfferings;
68 private VmsLayersAvailability mLayersAvailability;
69
70 @Override
71 protected void setUp() throws Exception {
72 mLayersAvailability = new VmsLayersAvailability();
73 mOfferings = new HashSet<>();
74 super.setUp();
75 }
76
77 public void testNoOffering() {
78 assertTrue(mLayersAvailability.getAvailableLayers().isEmpty());
79 }
80
81 public void testEmptyOffering() {
82 mLayersAvailability.setPublishersOffering(Collections.EMPTY_LIST);
83 assertTrue(mLayersAvailability.getAvailableLayers().isEmpty());
84 }
85
86 public void testSingleLayerNoDeps() throws Exception {
87 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
88 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_2));
89
90 VmsLayersOffering offering =
91 new VmsLayersOffering(new HashSet<>(Arrays.asList(new VmsLayerDependency(LAYER_X))),
92 PUBLISHER_ID_2);
93
94 mOfferings.add(offering);
95 mLayersAvailability.setPublishersOffering(mOfferings);
96
97 assertEquals(expectedAvailableAssociatedLayers, mLayersAvailability.getAvailableLayers());
98 }
99
100 public void testChainOfDependenciesSatisfied() throws Exception {
101 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
102 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
103 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Y, PUBLISHERS_1));
104 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Z, PUBLISHERS_1));
105
106 VmsLayersOffering offering =
107 new VmsLayersOffering(
108 new HashSet<>(Arrays.asList(X_DEPENDS_ON_Y, Y_DEPENDS_ON_Z, Z_DEPENDS_ON_NOTHING)),
109 PUBLISHER_ID_1);
110
111 mOfferings.add(offering);
112 mLayersAvailability.setPublishersOffering(mOfferings);
113
114 assertEquals(expectedAvailableAssociatedLayers,
115 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
116 }
117
118 public void testChainOfDependenciesSatisfiedTwoOfferings() throws Exception {
119 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
120 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
121 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Y, PUBLISHERS_1));
122 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Z, PUBLISHERS_1));
123
124 VmsLayersOffering offering1 =
125 new VmsLayersOffering(
126 new HashSet<>(Arrays.asList(X_DEPENDS_ON_Y, Y_DEPENDS_ON_Z)),
127 PUBLISHER_ID_1);
128
129 VmsLayersOffering offering2 =
130 new VmsLayersOffering(new HashSet<>(Arrays.asList(Z_DEPENDS_ON_NOTHING)),
131 PUBLISHER_ID_1);
132
133 mOfferings.add(offering1);
134 mOfferings.add(offering2);
135 mLayersAvailability.setPublishersOffering(mOfferings);
136
137 assertEquals(expectedAvailableAssociatedLayers,
138 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
139 }
140
141 public void testChainOfDependencieNotSatisfied() throws Exception {
142 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
143 VmsLayersOffering offering =
144 new VmsLayersOffering(new HashSet<>(Arrays.asList(X_DEPENDS_ON_Y, Y_DEPENDS_ON_Z)),
145 PUBLISHER_ID_1);
146
147 mOfferings.add(offering);
148 mLayersAvailability.setPublishersOffering(mOfferings);
149
150 assertEquals(expectedAvailableAssociatedLayers,
151 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
152
153 Set<VmsAssociatedLayer> expectedUnavailableAssociatedLayers = new HashSet<>();
154 expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
155 expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Y, PUBLISHERS_1));
156
157
158 assertEquals(expectedUnavailableAssociatedLayers,
159 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getUnavailableLayers()));
160 }
161
162 public void testOneOfMultipleDependencySatisfied() throws Exception {
163 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
164 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
165 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Z, PUBLISHERS_1));
166
167
168 VmsLayersOffering offering =
169 new VmsLayersOffering(
170 new HashSet<>(Arrays.asList(
171 X_DEPENDS_ON_Y, X_DEPENDS_ON_Z, Z_DEPENDS_ON_NOTHING)),
172 PUBLISHER_ID_1);
173
174 mOfferings.add(offering);
175 mLayersAvailability.setPublishersOffering(mOfferings);
176
177 assertEquals(expectedAvailableAssociatedLayers,
178 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
179 }
180
181 public void testCyclicDependency() throws Exception {
182 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
183
184 VmsLayersOffering offering =
185 new VmsLayersOffering(
186 new HashSet<>(
187 Arrays.asList(X_DEPENDS_ON_Y, Y_DEPENDS_ON_Z, Z_DEPENDS_ON_X)),
188 PUBLISHER_ID_1);
189
190 mOfferings.add(offering);
191 mLayersAvailability.setPublishersOffering(mOfferings);
192
193 assertEquals(expectedAvailableAssociatedLayers,
194 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
195 }
196
197 public void testAlmostCyclicDependency() throws Exception {
198 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
199 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Z, PUBLISHERS_1_AND_2));
200 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
201 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Y, PUBLISHERS_2));
202
203 VmsLayersOffering offering1 =
204 new VmsLayersOffering(
205 new HashSet<>(Arrays.asList(X_DEPENDS_ON_Y, Z_DEPENDS_ON_NOTHING)),
206 PUBLISHER_ID_1);
207
208 VmsLayersOffering offering2 =
209 new VmsLayersOffering(new HashSet<>(Arrays.asList(Y_DEPENDS_ON_Z, Z_DEPENDS_ON_X)),
210 PUBLISHER_ID_2);
211
212 mOfferings.add(offering1);
213 mOfferings.add(offering2);
214 mLayersAvailability.setPublishersOffering(mOfferings);
215
216 assertEquals(expectedAvailableAssociatedLayers, mLayersAvailability.getAvailableLayers());
217 }
218
219 public void testCyclicDependencyAndLayerWithoutDependency() throws Exception {
220 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
221 expectedAvailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Z, PUBLISHERS_1));
222
223 VmsLayersOffering offering1 =
224 new VmsLayersOffering(
225 new HashSet<>(
226 Arrays.asList(X_DEPENDS_ON_Y, Z_DEPENDS_ON_NOTHING)),
227 PUBLISHER_ID_1);
228
229 VmsLayersOffering offering2 =
230 new VmsLayersOffering(new HashSet<>(Arrays.asList(Y_DEPENDS_ON_X)), PUBLISHER_ID_2);
231
232 mOfferings.add(offering1);
233 mOfferings.add(offering2);
234 mLayersAvailability.setPublishersOffering(mOfferings);
235
236 assertEquals(expectedAvailableAssociatedLayers,
237 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
238
239 Set<VmsAssociatedLayer> expectedUnavailableAssociatedLayers = new HashSet<>();
240 expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
241 expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_Y, PUBLISHERS_2));
242
243 assertEquals(expectedUnavailableAssociatedLayers,
244 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getUnavailableLayers()));
245 }
246
247 public void testSelfDependency() throws Exception {
248 Set<VmsAssociatedLayer> expectedAvailableAssociatedLayers = new HashSet<>();
249
250 VmsLayersOffering offering =
251 new VmsLayersOffering(new HashSet<>(Arrays.asList(X_DEPENDS_ON_SELF)),
252 PUBLISHER_ID_1);
253
254 mOfferings.add(offering);
255 mLayersAvailability.setPublishersOffering(mOfferings);
256
257 assertEquals(expectedAvailableAssociatedLayers,
258 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getAvailableLayers()));
259
260 Set<VmsAssociatedLayer> expectedUnavailableAssociatedLayers = new HashSet<>();
261 expectedUnavailableAssociatedLayers.add(new VmsAssociatedLayer(LAYER_X, PUBLISHERS_1));
262
263 assertEquals(expectedUnavailableAssociatedLayers,
264 new HashSet<VmsAssociatedLayer>(mLayersAvailability.getUnavailableLayers()));
265 }
266} \ No newline at end of file
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
deleted file mode 100644
index 2b750129..00000000
--- a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
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
17package com.android.car;
18
19import android.car.annotation.FutureFeature;
20import android.test.AndroidTestCase;
21import android.test.suitebuilder.annotation.SmallTest;
22
23import java.util.Arrays;
24import java.util.Map;
25
26@FutureFeature
27@SmallTest
28public class VmsPublishersInfoTest extends AndroidTestCase {
29 public static final byte[] MOCK_INFO_0 = new byte[]{2, 3, 5, 7, 11, 13, 17};
30 public static final byte[] SAME_MOCK_INFO_0 = new byte[]{2, 3, 5, 7, 11, 13, 17};
31 public static final byte[] MOCK_INFO_1 = new byte[]{2, 3, 5, 7, 11, 13, 17, 19};
32
33 private VmsPublishersInfo mVmsPublishersInfo;
34
35 @Override
36 protected void setUp() throws Exception {
37 super.setUp();
38 mVmsPublishersInfo = new VmsPublishersInfo();
39 }
40
41 // Test one info sanity
42 public void testSingleInfo() throws Exception {
43 int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
44 assertEquals(0, id);
45
46 byte[] info = mVmsPublishersInfo.getPublisherInfo(id);
47 assertTrue(Arrays.equals(MOCK_INFO_0, info));
48 }
49
50 // Test one info sanity - wrong ID fails.
51 public void testSingleInfoWrongId() throws Exception {
52 int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
53 assertEquals(0, id);
54
55 try {
56 byte[] info = mVmsPublishersInfo.getPublisherInfo(id + 1);
57 }
58 catch (NullPointerException e) {
59 return;
60 }
61 fail();
62 }
63
64 // Test two infos.
65 public void testTwoInfos() throws Exception {
66 int id0 = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
67 int id1 = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_1);
68 assertEquals(0, id0);
69 assertEquals(1, id1);
70
71 byte[] info0 = mVmsPublishersInfo.getPublisherInfo(id0);
72 byte[] info1 = mVmsPublishersInfo.getPublisherInfo(id1);
73 assertTrue(Arrays.equals(MOCK_INFO_0, info0));
74 assertTrue(Arrays.equals(MOCK_INFO_1, info1));
75 }
76
77 // Test same info twice get the same ID.
78 public void testSingleInfoInsertedTwice() throws Exception {
79 int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
80 assertEquals(0, id);
81
82 int sameId = mVmsPublishersInfo.getIdForInfo(SAME_MOCK_INFO_0);
83 assertEquals(sameId, id);
84 }
85}
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsRoutingTest.java b/tests/carservice_unit_test/src/com/android/car/VmsRoutingTest.java
deleted file mode 100644
index 8fe849b7..00000000
--- a/tests/carservice_unit_test/src/com/android/car/VmsRoutingTest.java
+++ /dev/null
@@ -1,309 +0,0 @@
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
17package com.android.car;
18
19import android.car.vms.IVmsSubscriberClient;
20import android.car.vms.VmsAssociatedLayer;
21import android.car.vms.VmsLayer;
22import android.car.vms.VmsSubscriptionState;
23import android.test.AndroidTestCase;
24import android.test.suitebuilder.annotation.SmallTest;
25
26import java.util.ArrayList;
27import java.util.Arrays;
28import java.util.HashMap;
29import java.util.HashSet;
30import java.util.List;
31import java.util.Set;
32import java.util.Map;
33
34@SmallTest
35public class VmsRoutingTest extends AndroidTestCase {
36 private static VmsLayer LAYER_WITH_SUBSCRIPTION_1 = new VmsLayer(1, 1, 2);
37 private static VmsLayer LAYER_WITH_SUBSCRIPTION_2 = new VmsLayer(1, 3, 3);
38 private static VmsLayer LAYER_WITHOUT_SUBSCRIPTION =
39 new VmsLayer(1, 7, 4);
40 private static int PUBLISHER_ID_1 = 123;
41 private static int PUBLISHER_ID_2 = 456;
42 private static int PUBLISHER_ID_UNLISTED = 789;
43 private VmsRouting mRouting;
44
45 @Override
46 protected void setUp() throws Exception {
47 super.setUp();
48 mRouting = new VmsRouting();
49 }
50
51 public void testAddingSubscribersAndHalLayersNoOverlap() throws Exception {
52 // Add a subscription to a layer.
53 MockVmsSubscriber subscriber = new MockVmsSubscriber();
54 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1);
55
56 // Add a HAL subscription.
57 mRouting.addHalSubscription(LAYER_WITH_SUBSCRIPTION_2);
58
59 // Verify expected subscriptions are in routing manager.
60 Set<VmsLayer> expectedSubscriptions = new HashSet<>();
61 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_1);
62 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_2);
63 VmsSubscriptionState subscriptionState = mRouting.getSubscriptionState();
64 assertEquals(2, subscriptionState.getSequenceNumber());
65 assertEquals(expectedSubscriptions,
66 new HashSet<>(subscriptionState.getLayers()));
67
68 // Verify there is only a single subscriber.
69 assertEquals(1,
70 mRouting.getSubscribersForLayerFromPublisher(
71 LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1).size());
72 }
73
74 public void testAddingSubscribersAndHalLayersWithOverlap() throws Exception {
75 // Add a subscription to a layer.
76 MockVmsSubscriber subscriber = new MockVmsSubscriber();
77 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1);
78 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_2);
79
80 // Add a HAL subscription to a layer there is already another subscriber for.
81 mRouting.addHalSubscription(LAYER_WITH_SUBSCRIPTION_2);
82
83 // Verify expected subscriptions are in routing manager.
84 Set<VmsLayer> expectedSubscriptions = new HashSet<>();
85 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_1);
86 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_2);
87 VmsSubscriptionState subscriptionState = mRouting.getSubscriptionState();
88 assertEquals(3, subscriptionState.getSequenceNumber());
89 assertEquals(expectedSubscriptions,
90 new HashSet<>(subscriptionState.getLayers()));
91 }
92
93 public void testAddingAndRemovingLayers() throws Exception {
94 // Add a subscription to a layer.
95 MockVmsSubscriber subscriber = new MockVmsSubscriber();
96 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1);
97
98 // Add a HAL subscription.
99 mRouting.addHalSubscription(LAYER_WITH_SUBSCRIPTION_2);
100
101 // Remove a subscription to a layer.
102 mRouting.removeSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1);
103
104 // Update the HAL subscription
105 mRouting.removeHalSubscription(LAYER_WITH_SUBSCRIPTION_2);
106
107 // Verify there are no subscribers in the routing manager.
108 VmsSubscriptionState subscriptionState = mRouting.getSubscriptionState();
109 assertEquals(4, subscriptionState.getSequenceNumber());
110 assertTrue(subscriptionState.getLayers().isEmpty());
111 }
112
113 public void testAddingBothTypesOfSubscribers() throws Exception {
114 // Add a subscription to a layer.
115 MockVmsSubscriber subscriberForLayer = new MockVmsSubscriber();
116 mRouting.addSubscription(subscriberForLayer, LAYER_WITH_SUBSCRIPTION_1);
117
118 // Add a subscription without a layer.
119 MockVmsSubscriber subscriberWithoutLayer = new MockVmsSubscriber();
120 mRouting.addSubscription(subscriberWithoutLayer);
121
122 // Verify 2 subscribers for the layer.
123 assertEquals(2,
124 mRouting.getSubscribersForLayerFromPublisher(
125 LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1).size());
126
127 // Add the subscriber with layer as also a subscriber without layer
128 mRouting.addSubscription(subscriberForLayer);
129
130 // The number of subscribers for the layer should remain the same as before.
131 assertEquals(2,
132 mRouting.getSubscribersForLayerFromPublisher(
133 LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1).size());
134 }
135
136 public void testOnlyRelevantSubscribers() throws Exception {
137 // Add a subscription to a layer.
138 MockVmsSubscriber subscriberForLayer = new MockVmsSubscriber();
139 mRouting.addSubscription(subscriberForLayer, LAYER_WITH_SUBSCRIPTION_1);
140
141 // Add a subscription without a layer.
142 MockVmsSubscriber subscriberWithoutLayer = new MockVmsSubscriber();
143 mRouting.addSubscription(subscriberWithoutLayer);
144
145 // Verify that only the subscriber without layer is returned.
146 Set<MockVmsSubscriber> expectedListeneres = new HashSet<MockVmsSubscriber>();
147 expectedListeneres.add(subscriberWithoutLayer);
148 assertEquals(expectedListeneres,
149 mRouting.getSubscribersForLayerFromPublisher(
150 LAYER_WITHOUT_SUBSCRIPTION, PUBLISHER_ID_1));
151 }
152
153 public void testAddingSubscribersAndHalLayersAndSubscribersToPublishers() throws Exception {
154 // Add a subscription to a layer.
155 MockVmsSubscriber subscriber = new MockVmsSubscriber();
156 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1);
157
158 // Add a HAL subscription.
159 mRouting.addHalSubscription(LAYER_WITH_SUBSCRIPTION_2);
160
161 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1);
162 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_2);
163 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_2, PUBLISHER_ID_2);
164
165 // Verify expected subscriptions are in routing manager.
166 Set<VmsLayer> expectedSubscriptions = new HashSet<>();
167 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_1);
168 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_2);
169
170 Set<VmsAssociatedLayer> expectedSubscriptionsToPublishers = new HashSet<>();
171 expectedSubscriptionsToPublishers.add(new VmsAssociatedLayer(LAYER_WITH_SUBSCRIPTION_1,
172 new HashSet(Arrays.asList(PUBLISHER_ID_1, PUBLISHER_ID_2))));
173 expectedSubscriptionsToPublishers.add(new VmsAssociatedLayer(LAYER_WITH_SUBSCRIPTION_2,
174 new HashSet(Arrays.asList(PUBLISHER_ID_2))));
175
176 VmsSubscriptionState subscriptionState = mRouting.getSubscriptionState();
177 assertEquals(5, subscriptionState.getSequenceNumber());
178 assertEquals(expectedSubscriptions,
179 new HashSet<>(subscriptionState.getLayers()));
180
181 assertEquals(expectedSubscriptionsToPublishers,
182 subscriptionState.getAssociatedLayers());
183
184 // Verify there is only a single subscriber.
185 assertEquals(1,
186 mRouting.getSubscribersForLayerFromPublisher(
187 LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1).size());
188 }
189
190 public void testAddingSubscriberToPublishersAndGetListeneresToDifferentPublisher()
191 throws Exception {
192 // Add a subscription to a layer.
193 MockVmsSubscriber subscriber = new MockVmsSubscriber();
194
195 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_2);
196 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1);
197
198 Set<IVmsSubscriberClient> subscribers;
199 // Need to route a layer 1 message from publisher 2 so there are no subscribers.
200 subscribers =
201 mRouting.getSubscribersForLayerFromPublisher(
202 LAYER_WITH_SUBSCRIPTION_1,
203 PUBLISHER_ID_2);
204 assertEquals(0, subscribers.size());
205
206 // Need to route a layer 1 message from publisher 1 so there is one subscriber.
207 subscribers =
208 mRouting.getSubscribersForLayerFromPublisher(
209 LAYER_WITH_SUBSCRIPTION_1,
210 PUBLISHER_ID_1);
211 assertEquals(1, subscribers.size());
212 assertTrue(subscribers.contains(subscriber));
213
214 // Verify all the messages for LAYER_WITH_SUBSCRIPTION_2 have subscribers since the
215 // subscription was done without specifying a specific publisher.
216 subscribers =
217 mRouting.getSubscribersForLayerFromPublisher(
218 LAYER_WITH_SUBSCRIPTION_2,
219 PUBLISHER_ID_UNLISTED);
220 assertEquals(1, subscribers.size());
221 assertTrue(subscribers.contains(subscriber));
222 }
223
224
225 public void testRemovalOfSubscribersToPublishers() throws Exception {
226 // Add a subscription to a layer.
227 MockVmsSubscriber subscriber = new MockVmsSubscriber();
228 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1);
229
230 // Add a HAL subscription.
231 mRouting.addHalSubscription(LAYER_WITH_SUBSCRIPTION_2);
232
233 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1);
234 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_2);
235 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_2, PUBLISHER_ID_2);
236 mRouting.removeSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_2, PUBLISHER_ID_2);
237
238 // Verify expected subscriptions are in routing manager.
239 Set<VmsLayer> expectedSubscriptions = new HashSet<>();
240 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_1);
241 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_2);
242
243
244 Set<VmsAssociatedLayer> expectedSubscriptionsToPublishers = new HashSet<>();
245 expectedSubscriptionsToPublishers.add(new VmsAssociatedLayer(LAYER_WITH_SUBSCRIPTION_1,
246 new HashSet(Arrays.asList(PUBLISHER_ID_1, PUBLISHER_ID_2))));
247
248 VmsSubscriptionState subscriptionState = mRouting.getSubscriptionState();
249 assertEquals(6, subscriptionState.getSequenceNumber());
250 assertEquals(expectedSubscriptions,
251 new HashSet<>(subscriptionState.getLayers()));
252
253 assertEquals(expectedSubscriptionsToPublishers,
254 subscriptionState.getAssociatedLayers());
255
256 // Verify there is only a single subscriber.
257 assertEquals(1,
258 mRouting.getSubscribersForLayerFromPublisher(
259 LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1).size());
260 }
261
262 public void testRemovalOfSubscribersToPublishersClearListForPublisher() throws Exception {
263 // Add a subscription to a layer.
264 MockVmsSubscriber subscriber = new MockVmsSubscriber();
265 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1);
266
267 // Add a HAL subscription.
268 mRouting.addHalSubscription(LAYER_WITH_SUBSCRIPTION_2);
269
270 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1);
271 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_2);
272 mRouting.addSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_2, PUBLISHER_ID_2);
273 mRouting.removeSubscription(subscriber, LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1);
274
275 // Verify expected subscriptions are in routing manager.
276 Set<VmsLayer> expectedSubscriptions = new HashSet<>();
277 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_1);
278 expectedSubscriptions.add(LAYER_WITH_SUBSCRIPTION_2);
279
280 Set<VmsAssociatedLayer> expectedSubscriptionsToPublishers = new HashSet<>();
281 expectedSubscriptionsToPublishers.add(new VmsAssociatedLayer(LAYER_WITH_SUBSCRIPTION_1,
282 new HashSet(Arrays.asList(PUBLISHER_ID_2))));
283 expectedSubscriptionsToPublishers.add(new VmsAssociatedLayer(LAYER_WITH_SUBSCRIPTION_2,
284 new HashSet(Arrays.asList(PUBLISHER_ID_2))));
285
286 VmsSubscriptionState subscriptionState = mRouting.getSubscriptionState();
287 assertEquals(6, subscriptionState.getSequenceNumber());
288 assertEquals(expectedSubscriptions,
289 new HashSet<>(subscriptionState.getLayers()));
290
291 assertEquals(expectedSubscriptionsToPublishers,
292 subscriptionState.getAssociatedLayers());
293
294 // Verify there is only a single subscriber.
295 assertEquals(1,
296 mRouting.getSubscribersForLayerFromPublisher(
297 LAYER_WITH_SUBSCRIPTION_1, PUBLISHER_ID_1).size());
298 }
299
300 class MockVmsSubscriber extends IVmsSubscriberClient.Stub {
301 @Override
302 public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
303 }
304
305 @Override
306 public void onLayersAvailabilityChanged(List<VmsAssociatedLayer> availableLayers) {
307 }
308 }
309} \ No newline at end of file