Merge "Fix bootanalyze reading of dmesg"
diff --git a/car-lib/src/android/car/vms/IVmsPublisherService.aidl b/car-lib/src/android/car/vms/IVmsPublisherService.aidl
index 26b6e52..3312794 100644
--- a/car-lib/src/android/car/vms/IVmsPublisherService.aidl
+++ b/car-lib/src/android/car/vms/IVmsPublisherService.aidl
@@ -40,4 +40,11 @@
* Sets which layers the publisher can publish under which dependencties.
*/
oneway void setLayersOffering(in IBinder token, in VmsLayersOffering offering) = 2;
+
+ /**
+ * The first time a publisher calls this API it will store the publisher info and assigns the
+ * publisher a static ID. Between reboots, subsequent calls with the same publisher info will
+ * return the same ID so that a restarting process can obtain the same ID as it had before.
+ */
+ int getPublisherStaticId(in byte[] publisherInfo) = 3;
}
diff --git a/car-lib/src/android/car/vms/IVmsSubscriberService.aidl b/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
index 236ae5a..9234134 100644
--- a/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
+++ b/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
@@ -52,8 +52,12 @@
in IVmsSubscriberClient listener) = 3;
/**
- * Tells the VmsSubscriberService a client requests the list of available layers.
- * The service should call the client's onLayersAvailabilityChange in response.
+ * Returns a list of available layers from the closure of the publishers offerings.
*/
List<VmsLayer> getAvailableLayers() = 4;
+
+ /**
+ * Returns a the publisher information for a publisher ID.
+ */
+ byte[] getPublisherInfo(in int publisherId) = 5;
}
diff --git a/car-lib/src/android/car/vms/VmsPublisherClientService.java b/car-lib/src/android/car/vms/VmsPublisherClientService.java
index 85fd2c2..ea265df 100644
--- a/car-lib/src/android/car/vms/VmsPublisherClientService.java
+++ b/car-lib/src/android/car/vms/VmsPublisherClientService.java
@@ -155,6 +155,23 @@
return token;
}
+ public final int getPublisherStaticId(byte[] publisherInfo) {
+ if (mVmsPublisherService == null) {
+ throw new IllegalStateException("VmsPublisherService not set.");
+ }
+ Integer publisherStaticId = null;
+ try {
+ Log.i(TAG, "Getting publisher static ID");
+ publisherStaticId = mVmsPublisherService.getPublisherStaticId(publisherInfo);
+ } catch (RemoteException e) {
+ Log.e(TAG, "unable to invoke binder method.", e);
+ }
+ if (publisherStaticId == null) {
+ throw new IllegalStateException("VmsPublisherService cannot get a publisher static ID.");
+ }
+ return publisherStaticId;
+ }
+
/**
* Uses the VmsPublisherService binder to get the list of layer/version that have any
* subscribers.
diff --git a/car-lib/src/android/car/vms/VmsSubscriberManager.java b/car-lib/src/android/car/vms/VmsSubscriberManager.java
index 640948a..84405f4 100644
--- a/car-lib/src/android/car/vms/VmsSubscriberManager.java
+++ b/car-lib/src/android/car/vms/VmsSubscriberManager.java
@@ -157,6 +157,24 @@
}
/**
+ * Returns a serialized publisher information for a publisher ID.
+ */
+ public byte[] getPublisherInfo(int publisherId) throws CarNotConnectedException, IllegalStateException {
+ if (DBG) {
+ Log.d(TAG, "Getting all publishers info.");
+ }
+ try {
+ return mVmsSubscriberService.getPublisherInfo(publisherId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not connect: ", e);
+ throw new CarNotConnectedException(e);
+ } catch (IllegalStateException ex) {
+ Car.checkCarNotConnectedExceptionFromCarService(ex);
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ /**
* Subscribes to listen to the layer specified.
*
* @param layer the layer to subscribe to.
diff --git a/car_product/build/car_base.mk b/car_product/build/car_base.mk
index 6eaf3a5..658992b 100644
--- a/car_product/build/car_base.mk
+++ b/car_product/build/car_base.mk
@@ -84,12 +84,10 @@
# EVS resources
PRODUCT_PACKAGES += android.hardware.automotive.evs@1.0-service
+PRODUCT_PACKAGES += android.hardware.automotive.evs@1.0-sample
PRODUCT_PACKAGES += android.automotive.evs.manager@1.0
PRODUCT_PACKAGES += evs_app
-PRODUCT_COPY_FILES += \
- packages/services/Car/evs/app/config.json:system/etc/automotive/evs/config.json \
- packages/services/Car/evs/app/CarFromTop.png:system/etc/automotive/evs/CarFromTop.png \
- packages/services/Car/evs/app/LabeledChecker.png:system/etc/automotive/evs/LabeledChecker.png
+PRODUCT_PACKAGES += evs_app_resources
# Device running Android is a car
PRODUCT_COPY_FILES += \
diff --git a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action.xml b/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action.xml
index a5a670b..cefd830 100644
--- a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2014 The Android Open Source Project
+ ~ Copyright (C) 2017 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -14,18 +14,21 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<Button xmlns:android="http://schemas.android.com/apk/res/android"
+<Button
+ xmlns:android="http://schemas.android.com/apk/res/android"
style="@android:style/Widget.Material.Light.Button.Borderless.Small"
android:id="@+id/action0"
android:layout_width="wrap_content"
- android:layout_height="48dp"
+ android:layout_height="match_parent"
android:layout_gravity="center"
+ android:fontFamily="sans-serif"
android:gravity="start|center_vertical"
- android:layout_marginStart="4dp"
+ android:layout_marginStart="0dp"
android:textColor="@color/notification_default_color"
- android:textSize="24sp"
+ android:textSize="@dimen/notification_text_size"
+ android:textStyle="normal"
android:singleLine="true"
android:ellipsize="end"
- android:background="@drawable/notification_material_action_background"
- />
+ android:paddingStart="@dimen/notification_content_margin_start"
+ android:paddingEnd="@dimen/notification_content_margin_start"
+ android:background="@drawable/notification_material_action_background" />
diff --git a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_emphasized.xml b/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_emphasized.xml
deleted file mode 100644
index f4a0e12..0000000
--- a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_emphasized.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2016 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/button_holder"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:background="#ff000000">
- <Button
- style="@android:style/Widget.Material.Light.Button.Borderless.Small"
- android:id="@+id/action0"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:textColor="@color/notification_default_color"
- android:textSize="24sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:background="@drawable/notification_material_action_background"
- />
-</FrameLayout>
diff --git a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_list.xml b/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_list.xml
deleted file mode 100644
index 5488c43..0000000
--- a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_list.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/actions_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom">
- <com.android.internal.widget.NotificationActionListLayout
- android:id="@+id/actions"
- android:layout_width="match_parent"
- android:layout_height="@dimen/notification_action_list_height"
- android:paddingEnd="4dp"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:visibility="gone"
- android:background="@drawable/notification_action_bg"
- >
- <!-- actions will be added here -->
- </com.android.internal.widget.NotificationActionListLayout>
-</FrameLayout>
diff --git a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_tombstone.xml b/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_tombstone.xml
deleted file mode 100644
index ea184ef..0000000
--- a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_action_tombstone.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2014 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<Button xmlns:android="http://schemas.android.com/apk/res/android"
- style="@android:style/Widget.Material.Light.Button.Borderless.Small"
- android:id="@+id/action0"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:layout_marginStart="4dp"
- android:layout_gravity="center"
- android:gravity="start|center_vertical"
- android:textColor="#555555"
- android:textSize="24sp"
- android:singleLine="true"
- android:ellipsize="end"
- android:alpha="0.5"
- android:enabled="false"
- android:background="@drawable/notification_material_action_background"
- />
diff --git a/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_media_action.xml b/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_media_action.xml
new file mode 100644
index 0000000..29aafd4
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/layout/notification_material_media_action.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<ImageButton
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@android:style/Widget.Material.Button.Borderless.Small"
+ android:id="@+id/action0"
+ android:background="@drawable/notification_material_media_action_background"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/media_notification_action_button_size"
+ android:layout_weight="1"
+ android:padding="0dp"
+ android:gravity="center"
+ android:scaleType="fitCenter" />
diff --git a/car_product/overlay/frameworks/base/core/res/res/values-h600dp/dimens.xml b/car_product/overlay/frameworks/base/core/res/res/values-h600dp/dimens.xml
index b10cb31..b659bef 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values-h600dp/dimens.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values-h600dp/dimens.xml
@@ -30,4 +30,10 @@
is smaller than the notification_header_height to bring the text closer. Otherwise,
spacing in the font itself makes the space look too large. -->
<dimen name="notification_content_margin_top">68dp</dimen>
+
+ <!-- The height of the notification action list. -->
+ <dimen name="notification_action_list_height">96dp</dimen>
+
+ <!-- The size of the media actions in the media notification. -->
+ <dimen name="media_notification_action_button_size">56dp</dimen>
</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values-night/colors.xml b/car_product/overlay/frameworks/base/core/res/res/values-night/colors.xml
new file mode 100644
index 0000000..2774c9e
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/values-night/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <!-- The background color for the container of notification actions. -->
+ <color name="notification_action_list">#ff11181d</color> <!-- Dark Blue Grey 800 -->
+</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/colors.xml b/car_product/overlay/frameworks/base/core/res/res/values/colors.xml
new file mode 100644
index 0000000..f7a7a12
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <!-- The background color for the container of notification actions. -->
+ <color name="notification_action_list">#ffeeeeee</color> <!-- Grey 200 -->
+</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/dimens.xml b/car_product/overlay/frameworks/base/core/res/res/values/dimens.xml
index 553c890..125e1fb 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values/dimens.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values/dimens.xml
@@ -89,4 +89,19 @@
<!-- The margin on top of the text of the notification. -->
<dimen name="notification_text_margin_top">0dp</dimen>
+
+ <!-- The height of the notification action list. -->
+ <dimen name="notification_action_list_height">76dp</dimen>
+
+ <!-- The size of the media actions in the media notification. -->
+ <dimen name="media_notification_action_button_size">36dp</dimen>
+
+ <!-- The bottom padding for the media actions container. -->
+ <dimen name="media_notification_actions_padding_bottom">0dp</dimen>
+
+ <!-- The height of the progress bar. -->
+ <dimen name="notification_progress_bar_height">25dp</dimen>
+
+ <!-- The top margin before the notification progress bar. -->
+ <dimen name="notification_progress_margin_top">16dp</dimen>
</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/styles.xml b/car_product/overlay/frameworks/base/core/res/res/values/styles.xml
index de6f6ec..7bcedb9 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values/styles.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values/styles.xml
@@ -64,4 +64,15 @@
<item name="fragmentFadeEnterAnimation">@animator/fragment_fade_enter</item>
<item name="fragmentFadeExitAnimation">@animator/fragment_fade_exit</item>
</style>
+
+ <!-- The style for the container of media actions in a notification. -->
+ <style name="NotificationMediaActionContainer">
+ <item name="background">@color/notification_action_list</item>
+ <item name="layout_width">match_parent</item>
+ <item name="layout_height">@dimen/notification_action_list_height</item>
+ <item name="layout_marginTop">0dp</item>
+ <item name="paddingStart">0dp</item>
+ <item name="paddingBottom">@dimen/media_notification_actions_padding_bottom</item>
+ <item name="gravity">center</item>
+ </style>
</resources>
diff --git a/car_product/sepolicy/evs_app.te b/car_product/sepolicy/evs_app.te
new file mode 100644
index 0000000..0e8881e
--- /dev/null
+++ b/car_product/sepolicy/evs_app.te
@@ -0,0 +1,14 @@
+# evs app
+type evs_app, domain;
+type evs_app_exec, exec_type, file_type;
+
+allow evs_app evs_app_exec:dir search;
+allow evs_app evs_driver:binder call;
+allow evs_app evs_mock:binder call;
+allow evs_app gpu_device:chr_file ioctl;
+allow evs_app hal_graphics_allocator_default:fd use;
+allow evs_app hal_vehicle_default:binder call;
+
+init_daemon_domain(evs_app)
+
+binder_use(evs_app);
diff --git a/car_product/sepolicy/evs_driver.te b/car_product/sepolicy/evs_driver.te
new file mode 100644
index 0000000..1307616
--- /dev/null
+++ b/car_product/sepolicy/evs_driver.te
@@ -0,0 +1,12 @@
+# evs_driver mock hardware driver service
+type evs_driver, domain;
+type evs_driver_exec, exec_type, file_type;
+
+allow evs_driver hwservicemanager:binder { call transfer };
+allow evs_driver hwservicemanager_prop:file { getattr open read };
+allow evs_driver device:dir { open read };
+allow evs_driver surfaceflinger:binder call;
+
+init_daemon_domain(evs_driver)
+
+binder_use(evs_driver);
diff --git a/car_product/sepolicy/evs_manager.te b/car_product/sepolicy/evs_manager.te
new file mode 100644
index 0000000..f5c4ba8
--- /dev/null
+++ b/car_product/sepolicy/evs_manager.te
@@ -0,0 +1,11 @@
+# evs manager
+type evs_manager, domain;
+type evs_manager_exec, exec_type, file_type;
+
+allow evs_manager hwservicemanager:binder { call transfer };
+allow evs_manager hwservicemanager_prop:file { getattr open read };
+allow evs_manager evs_driver:binder call;
+
+init_daemon_domain(evs_manager)
+
+binder_use(evs_manager);
diff --git a/car_product/sepolicy/evs_mock.te b/car_product/sepolicy/evs_mock.te
new file mode 100644
index 0000000..b89b1ba
--- /dev/null
+++ b/car_product/sepolicy/evs_mock.te
@@ -0,0 +1,11 @@
+# evs_mock mock hardware driver service
+type evs_mock, domain;
+type evs_mock_exec, exec_type, file_type;
+
+allow evs_mock hwservicemanager:binder { call transfer };
+allow evs_mock hwservicemanager_prop:file { getattr open read };
+allow evs_mock hal_graphics_allocator_default:fd use;
+
+init_daemon_domain(evs_mock)
+
+binder_use(evs_mock);
diff --git a/car_product/sepolicy/file_contexts b/car_product/sepolicy/file_contexts
index 25cbef2..53759c7 100644
--- a/car_product/sepolicy/file_contexts
+++ b/car_product/sepolicy/file_contexts
@@ -6,4 +6,11 @@
/(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.vehicle@2\.0-service u:object_r:hal_vehicle_default_exec:s0
/(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.vehicle@2\.1-service u:object_r:hal_vehicle_default_exec:s0
+
+/(vendor|system/vendor)/bin/hw/android\.hardware\.automotive\.evs@1\.0-service u:object_r:evs_mock_exec:s0
+/system/bin/android\.hardware\.automotive\.evs@1\.0-sample u:object_r:evs_driver_exec:s0
+/system/bin/android\.automotive\.evs\.manager@1\.0 u:object_r:evs_manager_exec:s0
+/system/bin/evs_app u:object_r:evs_app_exec:s0
+/system/etc/automotive/evs(/.*)? u:object_r:evs_app_exec:s0
+
###################################
diff --git a/evs/app/Android.mk b/evs/app/Android.mk
index 784068d..7a81cbe 100644
--- a/evs/app/Android.mk
+++ b/evs/app/Android.mk
@@ -43,6 +43,8 @@
LOCAL_STRIP_MODULE := keep_symbols
+LOCAL_INIT_RC := evs_app.rc
+
LOCAL_MODULE:= evs_app
LOCAL_MODULE_TAGS := optional
@@ -50,3 +52,25 @@
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
include $(BUILD_EXECUTABLE)
+
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := config.json
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/system/etc/automotive/evs
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CarFromTop.png
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/system/etc/automotive/evs
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := LabeledChecker.png
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/system/etc/automotive/evs
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
diff --git a/evs/app/RenderTopView.cpp b/evs/app/RenderTopView.cpp
index a44f2af..1579a0a 100644
--- a/evs/app/RenderTopView.cpp
+++ b/evs/app/RenderTopView.cpp
@@ -265,8 +265,6 @@
glUniformMatrix4fv(loc, 1, false, orthoMatrix.asArray());
glBindTexture(GL_TEXTURE_2D, mTexAssets.carTopView->glId());
- printf("top view tex=%u\n", mTexAssets.carTopView->glId());
-
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -332,11 +330,9 @@
} else {
texId = mTexAssets.checkerBoard->glId();
}
- printf("projected tex=%u\n", texId);
glBindTexture(GL_TEXTURE_2D, texId);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- // glDrawArrays(GL_LINE_STRIP, 0, 4);
glDisableVertexAttribArray(0);
diff --git a/evs/app/config.json b/evs/app/config.json
index dedac44..5de8bb5 100644
--- a/evs/app/config.json
+++ b/evs/app/config.json
@@ -15,26 +15,26 @@
},
"cameras" : [
{
- "cameraId" : "/dev/video45",
+ "cameraId" : "/dev/video32",
"function" : "reverse,park",
"x" : 0.0,
"y" : -40.0,
"z" : 48,
"yaw" : 180,
"pitch" : -30,
- "hfov" : 90,
- "vfov" : 60
+ "hfov" : 125,
+ "vfov" :103
},
{
- "cameraId" : "/dev/video1",
+ "cameraId" : "/dev/video45",
"function" : "front,park",
"x" : 0.0,
"y" : 100.0,
"z" : 48,
"yaw" : 0,
"pitch" : -10,
- "hfov" : 60,
- "vfov" : 42
+ "hfov" : 70,
+ "vfov" : 43
},
{
"cameraId" : "/dev/video0",
diff --git a/evs/app/evs_app.rc b/evs/app/evs_app.rc
new file mode 100644
index 0000000..f040ff6
--- /dev/null
+++ b/evs/app/evs_app.rc
@@ -0,0 +1,9 @@
+service evs_app /system/bin/evs_app
+ class hal
+ priority -20
+ user automotive_evs
+ group automotive_evs
+
+#on post-fs
+#on boot
+# start evs_app
\ No newline at end of file
diff --git a/evs/manager/Android.mk b/evs/manager/Android.mk
index 912265e..fe384d9 100644
--- a/evs/manager/Android.mk
+++ b/evs/manager/Android.mk
@@ -21,6 +21,8 @@
android.hardware.automotive.evs@1.0 \
+LOCAL_INIT_RC := android.automotive.evs.manager@1.0.rc
+
LOCAL_MODULE := android.automotive.evs.manager@1.0
LOCAL_MODULE_TAGS := optional
diff --git a/evs/manager/android.automotive.evs.manager@1.0.rc b/evs/manager/android.automotive.evs.manager@1.0.rc
new file mode 100644
index 0000000..98d8792
--- /dev/null
+++ b/evs/manager/android.automotive.evs.manager@1.0.rc
@@ -0,0 +1,10 @@
+service evs_manager /system/bin/android.automotive.evs.manager@1.0
+ class hal
+ priority -20
+ user automotive_evs
+ group automotive_evs
+ onrestart restart evs_app
+
+#on post-fs
+#on boot
+# start evs_manager
diff --git a/evs/sampleDriver/Android.mk b/evs/sampleDriver/Android.mk
index 840c239..231ab6e 100644
--- a/evs/sampleDriver/Android.mk
+++ b/evs/sampleDriver/Android.mk
@@ -28,6 +28,7 @@
liblog \
libutils \
+LOCAL_INIT_RC := android.hardware.automotive.evs@1.0-sample.rc
LOCAL_MODULE := android.hardware.automotive.evs@1.0-sample
diff --git a/evs/sampleDriver/EvsV4lCamera.cpp b/evs/sampleDriver/EvsV4lCamera.cpp
index b30a23f..045d7ab 100644
--- a/evs/sampleDriver/EvsV4lCamera.cpp
+++ b/evs/sampleDriver/EvsV4lCamera.cpp
@@ -161,7 +161,8 @@
// Choose which image transfer function we need
// Map from V4L2 to Android graphic buffer format
const uint32_t videoSrcFormat = mVideo.getV4LFormat();
- ALOGI("Configuring to accept %4.4s camera data and convert to NV21", (char*)&videoSrcFormat);
+ ALOGI("Configuring to accept %4.4s camera data and convert to %4.4s",
+ (char*)&videoSrcFormat, (char*)&mFormat);
// TODO: Simplify this by supporting only ONE fixed output format
switch (mFormat) {
@@ -192,6 +193,7 @@
case HAL_PIXEL_FORMAT_YCBCR_422_I:
switch (videoSrcFormat) {
case V4L2_PIX_FMT_YUYV: mFillBufferFromVideo = fillYUYVFromYUYV; break;
+ case V4L2_PIX_FMT_UYVY: mFillBufferFromVideo = fillYUYVFromUYVY; break;
default:
// TODO: Are there other V4L2 formats we must support?
ALOGE("Unhandled camera format %4.4s", (char*)&videoSrcFormat);
diff --git a/evs/sampleDriver/GlWrapper.cpp b/evs/sampleDriver/GlWrapper.cpp
index 3747f7f..a49eb20 100644
--- a/evs/sampleDriver/GlWrapper.cpp
+++ b/evs/sampleDriver/GlWrapper.cpp
@@ -197,7 +197,11 @@
//
status_t err;
- mFlinger = new SurfaceComposerClient;
+ mFlinger = new SurfaceComposerClient();
+ if (mFlinger == nullptr) {
+ ALOGE("SurfaceComposerClient couldn't be allocated");
+ return false;
+ }
err = mFlinger->initCheck();
if (err != NO_ERROR) {
ALOGE("SurfaceComposerClient::initCheck error: %#x", err);
diff --git a/evs/sampleDriver/VideoCapture.cpp b/evs/sampleDriver/VideoCapture.cpp
index bb35310..2122a2c 100644
--- a/evs/sampleDriver/VideoCapture.cpp
+++ b/evs/sampleDriver/VideoCapture.cpp
@@ -94,9 +94,10 @@
// Set our desired output format
v4l2_format format;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; // Could/should we request V4L2_PIX_FMT_NV21?
+ format.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; // Could/should we request V4L2_PIX_FMT_NV21?
format.fmt.pix.width = 720; // TODO: Can we avoid hard coding dimensions?
format.fmt.pix.height = 240; // For now, this works with available hardware
+ format.fmt.pix.field = V4L2_FIELD_ALTERNATE; // TODO: Do we need to specify this?
ALOGI("Requesting format %c%c%c%c (0x%08X)",
((char*)&format.fmt.pix.pixelformat)[0],
((char*)&format.fmt.pix.pixelformat)[1],
diff --git a/evs/sampleDriver/android.hardware.automotive.evs@1.0-sample.rc b/evs/sampleDriver/android.hardware.automotive.evs@1.0-sample.rc
new file mode 100644
index 0000000..198b156
--- /dev/null
+++ b/evs/sampleDriver/android.hardware.automotive.evs@1.0-sample.rc
@@ -0,0 +1,10 @@
+service evs_driver /system/bin/android.hardware.automotive.evs@1.0-sample
+ class hal
+ priority -20
+ user automotive_evs
+ group automotive_evs
+ onrestart restart evs_manager
+
+#on post-fs
+#on boot
+# start evs_driver
diff --git a/evs/sampleDriver/bufferCopy.cpp b/evs/sampleDriver/bufferCopy.cpp
index e55170e..a585040 100644
--- a/evs/sampleDriver/bufferCopy.cpp
+++ b/evs/sampleDriver/bufferCopy.cpp
@@ -194,6 +194,41 @@
}
+void fillYUYVFromUYVY(const BufferDesc& tgtBuff, uint8_t* tgt, void* imgData, unsigned imgStride) {
+ unsigned width = tgtBuff.width;
+ unsigned height = tgtBuff.height;
+ uint32_t* src = (uint32_t*)imgData;
+ uint32_t* dst = (uint32_t*)tgt;
+ unsigned srcStridePixels = imgStride / 2;
+ unsigned dstStridePixels = tgtBuff.stride;
+
+ const int srcRowPadding32 = srcStridePixels/2 - width/2; // 2 bytes per pixel, 4 bytes per word
+ const int dstRowPadding32 = dstStridePixels/2 - width/2; // 2 bytes per pixel, 4 bytes per word
+
+ for (unsigned r=0; r<height; r++) {
+ for (unsigned c=0; c<width/2; c++) {
+ // Note: we're walking two pixels at a time here (even/odd)
+ uint32_t srcPixel = *src++;
+
+ uint8_t Y1 = (srcPixel) & 0xFF;
+ uint8_t U = (srcPixel >> 8) & 0xFF;
+ uint8_t Y2 = (srcPixel >> 16) & 0xFF;
+ uint8_t V = (srcPixel >> 24) & 0xFF;
+
+ // Now we write back the pair of pixels with the components swizzled
+ *dst++ = (U) |
+ (Y1 << 8) |
+ (V << 16) |
+ (Y2 << 24);
+ }
+
+ // Skip over any extra data or end of row alignment padding
+ src += srcRowPadding32;
+ dst += dstRowPadding32;
+ }
+}
+
+
} // namespace implementation
} // namespace V1_0
} // namespace evs
diff --git a/evs/sampleDriver/bufferCopy.h b/evs/sampleDriver/bufferCopy.h
index 8bf0b1f..9f68f2b 100644
--- a/evs/sampleDriver/bufferCopy.h
+++ b/evs/sampleDriver/bufferCopy.h
@@ -40,6 +40,9 @@
void fillYUYVFromYUYV(const BufferDesc& tgtBuff, uint8_t* tgt,
void* imgData, unsigned imgStride);
+void fillYUYVFromUYVY(const BufferDesc& tgtBuff, uint8_t* tgt,
+ void* imgData, unsigned imgStride);
+
} // namespace implementation
} // namespace V1_0
} // namespace evs
diff --git a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
index 072e2d6..4cdb640 100644
--- a/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
+++ b/service/src/com/android/car/BluetoothDeviceConnectionPolicy.java
@@ -652,6 +652,9 @@
// profile. When unpaired, we remove the device from all of the profiles' device list.
if (bondState == BluetoothDevice.BOND_NONE) {
for (Integer profile : mProfilesToConnect) {
+ if (DBG) {
+ Log.d(TAG, "Removing " + device + " from profile: " + profile);
+ }
removeDeviceFromProfile(device, profile);
}
}
@@ -1071,6 +1074,8 @@
}
for (BluetoothDevicesInfo devInfo : mProfileToConnectableDevicesMap.values()) {
writer.print("Profile: " + devInfo.getProfileLocked() + "\t");
+ writer.print(
+ "Num of Paired devices: " + devInfo.getNumberOfPairedDevicesLocked() + "\t");
writer.print("Active Connections: " + devInfo.getNumberOfActiveConnectionsLocked());
writer.println();
List<BluetoothDevicesInfo.DeviceInfo> deviceInfoList = devInfo.getDeviceInfoList();
diff --git a/service/src/com/android/car/BluetoothDevicesInfo.java b/service/src/com/android/car/BluetoothDevicesInfo.java
index eb77aad..a383f04 100644
--- a/service/src/com/android/car/BluetoothDevicesInfo.java
+++ b/service/src/com/android/car/BluetoothDevicesInfo.java
@@ -16,6 +16,7 @@
package com.android.car;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothDevice;
import android.util.Log;
@@ -27,7 +28,7 @@
/**
* BluetoothDevicesInfo contains all the information pertinent to connection on a Bluetooth Profile.
* It holds
- * 1. a list of devices {@link #mDeviceList} that has previously paired and connected on this
+ * 1. a list of devices {@link #mDeviceInfoList} that has previously paired and connected on this
* profile.
* 2. a Connection Info object {@link #mConnectionInfo} that has following book keeping information:
* a) profile
@@ -46,7 +47,6 @@
private static final String TAG = "CarBluetoothDevicesInfo";
private static final boolean DBG = false;
private final int DEVICE_NOT_FOUND = -1;
-
// The device list and the connection state information together have all the information
// that is required to know which device(s) to connect to, when we need to connect/
private List<DeviceInfo> mDeviceInfoList;
@@ -56,14 +56,20 @@
* This class holds on to information regarding this bluetooth profile's connection state.
*/
private class ConnectionInfo {
-
- int mProfile; // which bluetooth profile this Device Info is for
- boolean mDeviceAvailableToConnect; // known devices available to connect on this profile.
- int mDeviceIndex; // position of this device in the device List.
- int mNumPairedDevices; // Number of paired & connected devices for this profile
- int mRetryAttempt; // Connection Retry counter
- int mNumActiveConnections; // Current number of active connections on this profile
- int mNumConnectionsSupported; // number of concurrent active connections supported.
+ // which bluetooth profile this Device Info is for
+ private int mProfile;
+ // are there any devices available to connect. It is false either if
+ // 1. no device has been paired to connect on this profile
+ // 2. all paired devices have been tried to connect to, but unsuccessful (not in range etc)
+ private boolean mDeviceAvailableToConnect;
+ // index of device in the mDeviceInfoList that the next connection attempt should be made
+ private int mDeviceIndex;
+ // Connection Retry counter
+ private int mRetryAttempt;
+ // Current number of active connections on this profile
+ private int mNumActiveConnections;
+ // number of concurrent active connections supported.
+ private int mNumConnectionsSupported;
public ConnectionInfo(int profile) {
// Default the number of concurrent active connections supported to 1.
@@ -79,7 +85,6 @@
private void initConnectionInfo() {
mDeviceAvailableToConnect = true;
mDeviceIndex = 0;
- mNumPairedDevices = 0;
mRetryAttempt = 0;
mNumActiveConnections = 0;
}
@@ -164,6 +169,17 @@
return isPresent;
}
+ private DeviceInfo findDeviceInfoInListLocked(@Nullable BluetoothDevice device) {
+ if (device == null) {
+ return null;
+ }
+ for (DeviceInfo devInfo : mDeviceInfoList) {
+ if (devInfo.mBluetoothDevice.getAddress().equals(device.getAddress())) {
+ return devInfo;
+ }
+ }
+ return null;
+ }
/**
* Get the current list of connectable devices for this profile.
*
@@ -198,7 +214,7 @@
// Check if this device is already in the device list
if (checkDeviceInListLocked(dev)) {
if (DBG) {
- Log.d(TAG, "Device " + dev.getName() + "already in list. Not adding");
+ Log.d(TAG, "Device " + dev + " already in list. Not adding");
}
return;
}
@@ -211,14 +227,6 @@
Log.d(TAG, "Device List is null");
}
}
- // Increment the number of paired devices for this profile.
- if (mConnectionInfo != null) {
- mConnectionInfo.mNumPairedDevices++;
- } else {
- if (DBG) {
- Log.d(TAG, "Unexpected: ConnectionInfo is null");
- }
- }
}
/**
@@ -239,7 +247,7 @@
}
if (dev.getAddress().equals(device.getAddress())) {
if (DBG) {
- Log.d(TAG, "Setting " + dev.getName() + " state to " + state);
+ Log.d(TAG, "Setting " + dev + " state to " + state);
}
devInfo.setConnectionState(state);
break;
@@ -280,19 +288,22 @@
*/
public void removeDeviceLocked(BluetoothDevice dev) {
if (mDeviceInfoList != null) {
- mDeviceInfoList.remove(dev);
+ DeviceInfo devInfo = findDeviceInfoInListLocked(dev);
+ if (devInfo != null) {
+ mDeviceInfoList.remove(devInfo);
+ // If the device was connected when it was unpaired, we wouldn't have received the
+ // Profile disconnected intents. Hence check if the device was connected and if it
+ // was, then decrement the number of active connections.
+ if (devInfo.getConnectionState() == BluetoothProfile.STATE_CONNECTED) {
+ mConnectionInfo.mNumActiveConnections--;
+ }
+ }
} else {
if (DBG) {
Log.d(TAG, "Device List is null");
}
}
- if (mConnectionInfo != null) {
- mConnectionInfo.mNumPairedDevices--;
- } else {
- if (DBG) {
- Log.d(TAG, "ConnectionInfo is null");
- }
- }
+ Log.d(TAG, "Device List size: " + mDeviceInfoList.size());
}
public void clearDeviceListLocked() {
@@ -310,21 +321,34 @@
*/
public BluetoothDevice getNextDeviceInQueueLocked() {
BluetoothDevice device = null;
- if (mConnectionInfo.mDeviceIndex >= mConnectionInfo.mNumPairedDevices) {
+ int numberOfPairedDevices = getNumberOfPairedDevicesLocked();
+ if (mConnectionInfo.mDeviceIndex >= numberOfPairedDevices) {
if (DBG) {
Log.d(TAG,
"No device available for profile "
+ mConnectionInfo.mProfile + " "
+ mConnectionInfo.mDeviceIndex + "/"
- + mConnectionInfo.mNumPairedDevices);
+ + numberOfPairedDevices);
}
- mConnectionInfo.mDeviceIndex = 0; //reset the index
+ // mDeviceIndex is the index of the device in the mDeviceInfoList, that the next
+ // connection attempt would be made on. It is moved ahead on
+ // updateConnectionStatusLocked() so it always holds the index of the next device to
+ // connect to. But here, when we get the next device to connect to, if we see that
+ // the index is greater than the number of devices in the list, then we move the index
+ // back to the first device in the list and don't return anything.
+ // The reason why this is reset is to imply that connection attempts on this profile has
+ // been exhausted and if you want to retry connecting on this profile, we will start
+ // from the first device.
+ // The reason to reset here rather than in updateConnectionStatusLocked() is to make
+ // sure we have the latest view of the numberOfPairedDevices before we say we have
+ // exhausted the list.
+ mConnectionInfo.mDeviceIndex = 0;
return null;
}
device = mDeviceInfoList.get(mConnectionInfo.mDeviceIndex).mBluetoothDevice;
if (DBG) {
Log.d(TAG, "Getting device " + mConnectionInfo.mDeviceIndex + " from list: "
- + device.getName());
+ + device);
}
return device;
}
@@ -347,18 +371,18 @@
}
if (success) {
if (DBG) {
- Log.d(TAG, mConnectionInfo.mProfile + " connected to " + device.getName());
+ Log.d(TAG, mConnectionInfo.mProfile + " connected to " + device);
}
// b/34722344 - TODO
// Get the position of this device in the device list maintained for this profile.
int positionInQ = getPositionInListLocked(device);
if (DBG) {
- Log.d(TAG, "Position of " + device.getName() + " in Q: " + positionInQ);
+ Log.d(TAG, "Position of " + device + " in Q: " + positionInQ);
}
// If the device that connected is not in the list, it could be because it is being
// paired and getting added to the device list for this profile for the first time.
if (positionInQ == DEVICE_NOT_FOUND) {
- Log.d(TAG, "Connected device not in Q: " + device.getName());
+ Log.d(TAG, "Connected device not in Q: " + device);
addDeviceLocked(device);
positionInQ = mDeviceInfoList.size() - 1;
} else if (positionInQ != mConnectionInfo.mDeviceIndex) {
@@ -370,7 +394,8 @@
// to remember which devices connected on which profile (regardless of the origin
// of the connection request) so it knows which device to connect the next time.
if (DBG) {
- Log.d(TAG, "Different device connected: " + device.getName());
+ Log.d(TAG, "Different device connected: " + device + " CurrIndex: "
+ + mConnectionInfo.mDeviceIndex);
}
}
@@ -450,8 +475,8 @@
*
* @return number of paired devices on this profile.
*/
- public Integer getNumberOfPairedDevicesLocked() {
- return mConnectionInfo.mNumPairedDevices;
+ public int getNumberOfPairedDevicesLocked() {
+ return mDeviceInfoList.size();
}
/**
@@ -521,13 +546,17 @@
mConnectionInfo.mDeviceIndex = 0;
mConnectionInfo.mRetryAttempt = 0;
mConnectionInfo.mDeviceAvailableToConnect = true;
+ for (DeviceInfo info : mDeviceInfoList) {
+ setConnectionStateLocked(info.getBluetoothDevice(),
+ BluetoothProfile.STATE_DISCONNECTED);
+ }
}
public void resetDeviceListLocked() {
if (mDeviceInfoList != null) {
mDeviceInfoList.clear();
- mConnectionInfo.mNumPairedDevices = 0;
}
resetConnectionInfoLocked();
}
+
}
diff --git a/service/src/com/android/car/VmsPublisherService.java b/service/src/com/android/car/VmsPublisherService.java
index 683c1c8..37d265a 100644
--- a/service/src/com/android/car/VmsPublisherService.java
+++ b/service/src/com/android/car/VmsPublisherService.java
@@ -144,6 +144,12 @@
return mHal.getSubscriptionState();
}
+ @Override
+ public int getPublisherStaticId(byte[] publisherInfo) {
+ ICarImpl.assertVmsPublisherPermission(mContext);
+ return mHal.getPublisherStaticId(publisherInfo);
+ }
+
// Implements VmsHalListener interface
/**
* This method is only invoked by VmsHalService.notifyPublishers which is synchronized.
diff --git a/service/src/com/android/car/VmsPublishersInfo.java b/service/src/com/android/car/VmsPublishersInfo.java
new file mode 100644
index 0000000..04ee82f
--- /dev/null
+++ b/service/src/com/android/car/VmsPublishersInfo.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car;
+
+
+import android.car.annotation.FutureFeature;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import com.android.internal.annotations.GuardedBy;
+import android.util.Log;
+
+@FutureFeature
+public class VmsPublishersInfo {
+ private static final String TAG = "VmsPublishersInfo";
+ private static final boolean DBG = true;
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private final Map<InfoWrapper, Integer> mPublishersIds = new HashMap();
+ @GuardedBy("mLock")
+ private final Map<Integer, byte[]> mPublishersInfo = new HashMap();
+
+ private static class InfoWrapper {
+ private final byte[] mInfo;
+
+ public InfoWrapper(byte[] info) {
+ mInfo = info;
+ }
+
+ public byte[] getInfo() {
+ return mInfo;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof InfoWrapper)) {
+ return false;
+ }
+ InfoWrapper p = (InfoWrapper) o;
+ return Arrays.equals(this.mInfo, p.mInfo);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(mInfo);
+ }
+ }
+
+ /**
+ * Returns the ID associated with the publisher info. When called for the first time for a
+ * publisher info will store the info and assign an ID
+ */
+ public int getIdForInfo(byte[] publisherInfo) {
+ Integer publisherId;
+ InfoWrapper wrappedPublisherInfo = new InfoWrapper(publisherInfo);
+ synchronized (mLock) {
+ maybeAddPublisherInfoLocked(wrappedPublisherInfo);
+ publisherId = mPublishersIds.get(wrappedPublisherInfo);
+ }
+ if (DBG) {
+ Log.i(TAG, "Publisher ID is: " + publisherId);
+ }
+ return publisherId;
+ }
+
+ public byte[] getPublisherInfo(int publisherId) {
+ synchronized (mLock) {
+ return mPublishersInfo.get(publisherId).clone();
+ }
+ }
+
+ private void maybeAddPublisherInfoLocked(InfoWrapper wrappedPublisherInfo) {
+ if (!mPublishersIds.containsKey(wrappedPublisherInfo)) {
+ // Assign ID to the info
+ Integer publisherId = mPublishersIds.size();
+
+ mPublishersIds.put(wrappedPublisherInfo, publisherId);
+ mPublishersInfo.put(publisherId, wrappedPublisherInfo.getInfo());
+ }
+ }
+}
+
diff --git a/service/src/com/android/car/VmsSubscriberService.java b/service/src/com/android/car/VmsSubscriberService.java
index eabb0a6..fc0a885 100644
--- a/service/src/com/android/car/VmsSubscriberService.java
+++ b/service/src/com/android/car/VmsSubscriberService.java
@@ -262,6 +262,13 @@
}
@Override
+ public byte[] getPublisherInfo(int publisherId) {
+ synchronized (mSubscriberServiceLock) {
+ return mHal.getPublisherInfo(publisherId);
+ }
+ }
+
+ @Override
public List<VmsLayer> getAvailableLayers() {
//TODO(asafro): return the list of available layers once logic is implemented.
return Collections.emptyList();
diff --git a/service/src/com/android/car/hal/VmsHalService.java b/service/src/com/android/car/hal/VmsHalService.java
index b294985..8ab5427 100644
--- a/service/src/com/android/car/hal/VmsHalService.java
+++ b/service/src/com/android/car/hal/VmsHalService.java
@@ -37,6 +37,7 @@
import android.util.Log;
import com.android.car.CarLog;
import com.android.car.VmsLayersAvailability;
+import com.android.car.VmsPublishersInfo;
import com.android.car.VmsRouting;
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
@@ -71,13 +72,13 @@
private final IBinder mHalPublisherToken = new Binder();
private final VehicleHal mVehicleHal;
- private final Object mRoutingLock = new Object();
+ private final Object mLock = new Object();
private final VmsRouting mRouting = new VmsRouting();
- private final Object mAvailabilityLock = new Object();
- @GuardedBy("mAvailabilityLock")
+ @GuardedBy("mLock")
private final Map<IBinder, VmsLayersOffering> mOfferings = new HashMap<>();
- @GuardedBy("mAvailabilityLock")
+ @GuardedBy("mLock")
private final VmsLayersAvailability mAvailableLayers = new VmsLayersAvailability();
+ private final VmsPublishersInfo mPublishersInfo = new VmsPublishersInfo();
/**
* The VmsPublisherService implements this interface to receive data from the HAL.
@@ -125,7 +126,7 @@
public void addSubscription(IVmsSubscriberClient listener, VmsLayer layer) {
boolean firstSubscriptionForLayer = false;
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
// Check if publishers need to be notified about this change in subscriptions.
firstSubscriptionForLayer = !mRouting.hasLayerSubscriptions(layer);
@@ -139,7 +140,7 @@
public void removeSubscription(IVmsSubscriberClient listener, VmsLayer layer) {
boolean layerHasSubscribers = true;
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
if (!mRouting.hasLayerSubscriptions(layer)) {
Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
return;
@@ -157,50 +158,74 @@
}
public void addSubscription(IVmsSubscriberClient listener) {
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
mRouting.addSubscription(listener);
}
}
public void removeSubscription(IVmsSubscriberClient listener) {
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
mRouting.removeSubscription(listener);
}
}
public void removeDeadListener(IVmsSubscriberClient listener) {
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
mRouting.removeDeadListener(listener);
}
}
public Set<IVmsSubscriberClient> getListeners(VmsLayer layer) {
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
return mRouting.getListeners(layer);
}
}
public Set<IVmsSubscriberClient> getAllListeners() {
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
return mRouting.getAllListeners();
}
}
public boolean isHalSubscribed(VmsLayer layer) {
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
return mRouting.isHalSubscribed(layer);
}
}
public VmsSubscriptionState getSubscriptionState() {
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
return mRouting.getSubscriptionState();
}
}
+ /**
+ * Assigns an idempotent ID for publisherInfo and stores it. The idempotency in this case means
+ * that the same publisherInfo will always, within a trip of the vehicle, return the same ID.
+ * The publisherInfo should be static for a binary and should only change as part of a software
+ * update. The publisherInfo is a serialized proto message which VMS clients can interpret.
+ */
+ public int getPublisherStaticId(byte[] publisherInfo) {
+ if (DBG) {
+ Log.i(TAG, "Getting publisher static ID");
+ }
+ synchronized (mLock) {
+ return mPublishersInfo.getIdForInfo(publisherInfo);
+ }
+ }
+
+ public byte[] getPublisherInfo(int publisherId) {
+ if (DBG) {
+ Log.i(TAG, "Getting information for publisher ID: " + publisherId);
+ }
+ synchronized (mLock) {
+ return mPublishersInfo.getPublisherInfo(publisherId);
+ }
+ }
+
public void addHalSubscription(VmsLayer layer) {
boolean firstSubscriptionForLayer = true;
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
// Check if publishers need to be notified about this change in subscriptions.
firstSubscriptionForLayer = !mRouting.hasLayerSubscriptions(layer);
@@ -214,7 +239,7 @@
public void removeHalSubscription(VmsLayer layer) {
boolean layerHasSubscribers = true;
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
if (!mRouting.hasLayerSubscriptions(layer)) {
Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
return;
@@ -232,14 +257,14 @@
}
public boolean containsListener(IVmsSubscriberClient listener) {
- synchronized (mRoutingLock) {
+ synchronized (mLock) {
return mRouting.containsListener(listener);
}
}
public void setPublisherLayersOffering(IBinder publisherToken, VmsLayersOffering offering){
Set<VmsLayer> availableLayers = Collections.EMPTY_SET;
- synchronized (mAvailabilityLock) {
+ synchronized (mLock) {
updateOffering(publisherToken, offering);
availableLayers = mAvailableLayers.getAvailableLayers();
}
@@ -248,7 +273,7 @@
public Set<VmsLayer> getAvailableLayers() {
//TODO(b/36872877): wrap available layers in VmsAvailabilityState similar to VmsSubscriptionState.
- synchronized (mAvailabilityLock) {
+ synchronized (mLock) {
return mAvailableLayers.getAvailableLayers();
}
}
@@ -475,7 +500,7 @@
}
// Store the HAL offering.
VmsLayersOffering offering = new VmsLayersOffering(offeredLayers);
- synchronized (mAvailabilityLock) {
+ synchronized (mLock) {
updateOffering(mHalPublisherToken, offering);
}
}
@@ -489,7 +514,7 @@
* </ul>
*/
private void handleAvailabilityEvent() {
- synchronized (mAvailabilityLock) {
+ synchronized (mLock) {
Collection<VmsLayer> availableLayers = mAvailableLayers.getAvailableLayers();
VehiclePropValue vehiclePropertyValue = toVehiclePropValue(
VmsMessageType.AVAILABILITY_RESPONSE, availableLayers);
@@ -527,7 +552,7 @@
private void updateOffering(IBinder publisherToken, VmsLayersOffering offering) {
Set<VmsLayer> availableLayers = Collections.EMPTY_SET;
- synchronized (mAvailabilityLock) {
+ synchronized (mLock) {
mOfferings.put(publisherToken, offering);
// Update layers availability.
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java b/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
index 63492f8..d8e344b 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
+++ b/tests/carservice_test/src/com/android/car/test/VmsPublisherClientMockService.java
@@ -22,6 +22,7 @@
import android.car.vms.VmsLayersOffering;
import android.car.vms.VmsPublisherClientService;
import android.car.vms.VmsSubscriptionState;
+import android.util.Log;
import java.util.List;
import java.util.ArrayList;
@@ -35,18 +36,24 @@
*/
@FutureFeature
public class VmsPublisherClientMockService extends VmsPublisherClientService {
+ private static final String TAG = "VmsPublisherClientMockService";
@Override
public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) {
// Case when the publisher finished initialization before the subscription request.
- publishIfNeeded(subscriptionState);
- declareOffering(subscriptionState);
+ initializeMockPublisher(subscriptionState);
}
@Override
public void onVmsPublisherServiceReady() {
// Case when the subscription request was sent before the publisher was ready.
VmsSubscriptionState subscriptionState = getSubscriptions();
+ initializeMockPublisher(subscriptionState);
+ }
+
+ private void initializeMockPublisher(VmsSubscriptionState subscriptionState) {
+ Log.d(TAG, "Initializing Mock publisher");
+ getPublisherStaticId(VmsPublisherSubscriberTest.PAYLOAD);
publishIfNeeded(subscriptionState);
declareOffering(subscriptionState);
}
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java b/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
index 20fa0b6..3b3a94f 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
+++ b/tests/carservice_test/src/com/android/car/test/VmsPublisherSubscriberTest.java
@@ -29,13 +29,12 @@
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
import android.hardware.automotive.vehicle.V2_1.VehicleProperty;
-
import com.android.car.vehiclehal.test.MockedVehicleHal;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -43,6 +42,7 @@
public class VmsPublisherSubscriberTest extends MockedCarTestBase {
private static final int LAYER_ID = 88;
private static final int LAYER_VERSION = 19;
+ private static final int EXPECTED_PUBLISHER_ID = 0;
private static final String TAG = "VmsPubSubTest";
public static final VmsLayer LAYER = new VmsLayer(LAYER_ID, LAYER_VERSION);
@@ -127,6 +127,27 @@
}
/**
+ * The Mock service will get a publisher ID by sending its information when it will get
+ * ServiceReady as well as on SubscriptionChange. Since clients are not notified when
+ * publishers are assigned IDs, this test waits until the availability is changed which indicates
+ * that the Mock service has gotten its ServiceReady and publisherId.
+ */
+ public void testPublisherInfo() throws Exception {
+ if (!VmsTestUtils.canRunTest(TAG)) return;
+ VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ // Subscribe to layer as a way to make sure the mock client completed setting the information.
+ TestListener listener = new TestListener();
+ vmsSubscriberManager.setListener(listener);
+ vmsSubscriberManager.subscribe(LAYER);
+
+ assertTrue(mAvailabilitySemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+
+ byte[] info = vmsSubscriberManager.getPublisherInfo(EXPECTED_PUBLISHER_ID);
+ assertTrue(Arrays.equals(PAYLOAD, info));
+ }
+
+ /**
* The Mock service offers all the subscribed layers as available layers, so in this
* test the listener subscribes to a layer and verifies that it gets the notification that it
* is available.
diff --git a/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
new file mode 100644
index 0000000..2b75012
--- /dev/null
+++ b/tests/carservice_unit_test/src/com/android/car/VmsPublishersInfoTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car;
+
+import android.car.annotation.FutureFeature;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.Arrays;
+import java.util.Map;
+
+@FutureFeature
+@SmallTest
+public class VmsPublishersInfoTest extends AndroidTestCase {
+ public static final byte[] MOCK_INFO_0 = new byte[]{2, 3, 5, 7, 11, 13, 17};
+ public static final byte[] SAME_MOCK_INFO_0 = new byte[]{2, 3, 5, 7, 11, 13, 17};
+ public static final byte[] MOCK_INFO_1 = new byte[]{2, 3, 5, 7, 11, 13, 17, 19};
+
+ private VmsPublishersInfo mVmsPublishersInfo;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mVmsPublishersInfo = new VmsPublishersInfo();
+ }
+
+ // Test one info sanity
+ public void testSingleInfo() throws Exception {
+ int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
+ assertEquals(0, id);
+
+ byte[] info = mVmsPublishersInfo.getPublisherInfo(id);
+ assertTrue(Arrays.equals(MOCK_INFO_0, info));
+ }
+
+ // Test one info sanity - wrong ID fails.
+ public void testSingleInfoWrongId() throws Exception {
+ int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
+ assertEquals(0, id);
+
+ try {
+ byte[] info = mVmsPublishersInfo.getPublisherInfo(id + 1);
+ }
+ catch (NullPointerException e) {
+ return;
+ }
+ fail();
+ }
+
+ // Test two infos.
+ public void testTwoInfos() throws Exception {
+ int id0 = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
+ int id1 = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_1);
+ assertEquals(0, id0);
+ assertEquals(1, id1);
+
+ byte[] info0 = mVmsPublishersInfo.getPublisherInfo(id0);
+ byte[] info1 = mVmsPublishersInfo.getPublisherInfo(id1);
+ assertTrue(Arrays.equals(MOCK_INFO_0, info0));
+ assertTrue(Arrays.equals(MOCK_INFO_1, info1));
+ }
+
+ // Test same info twice get the same ID.
+ public void testSingleInfoInsertedTwice() throws Exception {
+ int id = mVmsPublishersInfo.getIdForInfo(MOCK_INFO_0);
+ assertEquals(0, id);
+
+ int sameId = mVmsPublishersInfo.getIdForInfo(SAME_MOCK_INFO_0);
+ assertEquals(sameId, id);
+ }
+}