Merge "Update notification actions."
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 e73603c..7c60150 100644
--- a/car_product/build/car_base.mk
+++ b/car_product/build/car_base.mk
@@ -84,6 +84,7 @@
# 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 += \
@@ -91,6 +92,10 @@
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
+# Device running Android is a car
+PRODUCT_COPY_FILES += \
+ frameworks/native/data/etc/android.hardware.type.automotive.xml:system/etc/permissions/android.hardware.type.automotive.xml
+
PRODUCT_PACKAGES += android.hardware.automotive.vehicle@2.1-service
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_minimal.mk)
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/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/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/CarAudioService.java b/service/src/com/android/car/CarAudioService.java
index 29012da..f2ee831 100644
--- a/service/src/com/android/car/CarAudioService.java
+++ b/service/src/com/android/car/CarAudioService.java
@@ -118,12 +118,8 @@
new MediaMuteAudioFocusListener();
@GuardedBy("mLock")
- private int mBottomFocusState;
- @GuardedBy("mLock")
private boolean mRadioOrExtSourceActive = false;
@GuardedBy("mLock")
- private boolean mCallActive = false;
- @GuardedBy("mLock")
private int mCurrentAudioContexts = 0;
@GuardedBy("mLock")
private int mCurrentPrimaryAudioContext = 0;
@@ -209,11 +205,6 @@
int r = mAudioManager.requestAudioFocus(mBottomAudioFocusListener, mAttributeBottom,
AudioManager.AUDIOFOCUS_GAIN, AudioManager.AUDIOFOCUS_FLAG_DELAY_OK);
synchronized (mLock) {
- if (r == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
- mBottomFocusState = AudioManager.AUDIOFOCUS_GAIN;
- } else {
- mBottomFocusState = AudioManager.AUDIOFOCUS_LOSS_TRANSIENT;
- }
mCurrentFocusState = currentState;
mCurrentAudioContexts = 0;
}
@@ -458,7 +449,7 @@
" mLastFocusRequestToCar:" + mLastFocusRequestToCar);
writer.println(" mCurrentAudioContexts:0x" +
Integer.toHexString(mCurrentAudioContexts));
- writer.println(" mCallActive:" + mCallActive + " mRadioOrExtSourceActive:" +
+ writer.println(" mRadioOrExtSourceActive:" +
mRadioOrExtSourceActive);
writer.println(" mCurrentPrimaryAudioContext:" + mCurrentPrimaryAudioContext +
" mCurrentPrimaryPhysicalStream:" + mCurrentPrimaryPhysicalStream);
@@ -985,11 +976,6 @@
CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE) {
muteMedia = true;
}
- if (logicalStreamTypeForTop == CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL) {
- mCallActive = true;
- } else {
- mCallActive = false;
- }
// other apps having focus
int focusToRequest = AudioHalService.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE;
int extFocus = AudioHalService.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG;
@@ -1578,9 +1564,6 @@
private class BottomAudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
@Override
public void onAudioFocusChange(int focusChange) {
- synchronized (mLock) {
- mBottomFocusState = focusChange;
- }
}
}
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);
+ }
+}
diff --git a/tools/bootanalyze/bootanalyze.py b/tools/bootanalyze/bootanalyze.py
index 4b814c7..8c13d6f 100755
--- a/tools/bootanalyze/bootanalyze.py
+++ b/tools/bootanalyze/bootanalyze.py
@@ -476,6 +476,16 @@
zygote_pids.append(pid)
events[event] = line
+def update_name_if_already_exist(events, name):
+ existing_event = events.get(name)
+ i = 0
+ new_name = name
+ while existing_event:
+ i += 1
+ new_name = name + "_" + str(i)
+ existing_event = events.get(new_name)
+ return new_name
+
def collect_events(search_events, command, timings, stop_events, disable_timing_after_zygote):
events = collections.OrderedDict()
timing_events = {}
@@ -512,7 +522,8 @@
elif event.startswith("zygote"):
handle_zygote_event(zygote_pids, events, event, line)
else:
- events[event] = line
+ new_event = update_name_if_already_exist(events, event)
+ events[new_event] = line
if event in stop_events:
stop_events.remove(event)
print "remaining stop_events:", stop_events
diff --git a/tools/bootanalyze/config.yaml b/tools/bootanalyze/config.yaml
index 923ca5d..9d322ed 100644
--- a/tools/bootanalyze/config.yaml
+++ b/tools/bootanalyze/config.yaml
@@ -43,6 +43,8 @@
CarLauncherReady: Em.Overview:\s*onResume
CarService_start: for service com.android.car/.CarService
BootAnimStart: starting service 'bootanim'
+ BootAnimSfWait: BootAnimation:\sWaiting\sfor\sSurfaceFlinger\stook\s
+ BootAnimShowStart: BootAnimation:\sBootAnimationShownTiming\sstart\stime
BootAnimStopRequest: TELLING SURFACE FLINGER WE ARE BOOTED
BootAnimEnd: Service 'bootanim'
KeyguardStart: KeyguardServiceDelegate.*\*\*\* Keyguard started