Merge "Add intent action and extra for car media template app." into oc-mr1-dev
diff --git a/car-lib/src/android/car/vms/IVmsSubscriberService.aidl b/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
index 9234134..fd610ce 100644
--- a/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
+++ b/car-lib/src/android/car/vms/IVmsSubscriberService.aidl
@@ -24,40 +24,57 @@
*/
interface IVmsSubscriberService {
/**
- * Subscribes the listener to receive messages from layer/version.
+ * Adds a subscriber to a VMS layer.
*/
- void addVmsSubscriberClientListener(
- in IVmsSubscriberClient listener,
+ void addVmsSubscriber(
+ in IVmsSubscriberClient subscriber,
in VmsLayer layer) = 0;
/**
- * Subscribes the listener to receive messages from all published layer/version. The
- * service will not send any subscription notifications to publishers (i.e. this is a passive
- * subscriber).
+ * Adds a subscriber to all actively broadcasted layers.
+ * Publishers will not be notified regarding this request so the state of the service will not
+ * change.
*/
- void addVmsSubscriberClientPassiveListener(in IVmsSubscriberClient listener) = 1;
+ void addVmsSubscriberPassive(in IVmsSubscriberClient subscriber) = 1;
/**
- * Tells the VmsSubscriberService a client unsubscribes to layer messages.
- */
- void removeVmsSubscriberClientListener(
- in IVmsSubscriberClient listener,
- in VmsLayer layer) = 2;
+ * Adds a subscriber to a VMS layer from a specific publisher.
+ */
+ void addVmsSubscriberToPublisher(
+ in IVmsSubscriberClient subscriber,
+ in VmsLayer layer,
+ int publisherId) = 2;
/**
- * Tells the VmsSubscriberService a passive client unsubscribes. This will not unsubscribe
- * the listener from any specific layer it has subscribed to.
+ * Removes a subscriber to a VMS layer.
*/
- void removeVmsSubscriberClientPassiveListener(
- in IVmsSubscriberClient listener) = 3;
+ void removeVmsSubscriber(
+ in IVmsSubscriberClient subscriber,
+ in VmsLayer layer) = 3;
+
+ /**
+ * Removes a subscriber to all actively broadcasted layers.
+ * Publishers will not be notified regarding this request so the state of the service will not
+ * change.
+ */
+ void removeVmsSubscriberPassive(
+ in IVmsSubscriberClient subscriber) = 4;
+
+ /**
+ * Removes a subscriber to a VMS layer from a specific publisher.
+ */
+ void removeVmsSubscriberToPublisher(
+ in IVmsSubscriberClient subscriber,
+ in VmsLayer layer,
+ int publisherId) = 5;
/**
* Returns a list of available layers from the closure of the publishers offerings.
*/
- List<VmsLayer> getAvailableLayers() = 4;
+ List<VmsLayer> getAvailableLayers() = 6;
/**
* Returns a the publisher information for a publisher ID.
*/
- byte[] getPublisherInfo(in int publisherId) = 5;
+ byte[] getPublisherInfo(in int publisherId) = 7;
}
diff --git a/car-lib/src/android/car/vms/VmsOperationRecorder.java b/car-lib/src/android/car/vms/VmsOperationRecorder.java
index 6ddd6fa..7bac812 100644
--- a/car-lib/src/android/car/vms/VmsOperationRecorder.java
+++ b/car-lib/src/android/car/vms/VmsOperationRecorder.java
@@ -50,6 +50,14 @@
recordOp("unsubscribe", layer);
}
+ public void subscribe(VmsLayer layer, int publisherId) {
+ recordOp("subscribe", "publisherId", publisherId, layer);
+ }
+
+ public void unsubscribe(VmsLayer layer, int publisherId) {
+ recordOp("unsubscribe", "publisherId", publisherId, layer);
+ }
+
public void subscribeAll() {
recordOp("subscribeAll");
}
diff --git a/car-lib/src/android/car/vms/VmsSubscriberManager.java b/car-lib/src/android/car/vms/VmsSubscriberManager.java
index 97447b9..a426f92 100644
--- a/car-lib/src/android/car/vms/VmsSubscriberManager.java
+++ b/car-lib/src/android/car/vms/VmsSubscriberManager.java
@@ -52,15 +52,23 @@
@GuardedBy("mListenerLock")
private VmsSubscriberClientListener mListener;
- /** Interface exposed to VMS subscribers: it is a wrapper of IVmsSubscriberClient. */
+ /**
+ * Interface exposed to VMS subscribers: it is a wrapper of IVmsSubscriberClient.
+ */
public interface VmsSubscriberClientListener {
- /** Called when the property is updated */
+ /**
+ * Called when the property is updated
+ */
void onVmsMessageReceived(VmsLayer layer, byte[] payload);
- /** Called when layers availability change */
+ /**
+ * Called when layers availability change
+ */
void onLayersAvailabilityChange(List<VmsLayer> availableLayers);
- /** Notifies the client of the disconnect event */
+ /**
+ * Notifies the client of the disconnect event
+ */
void onCarDisconnected();
}
@@ -68,7 +76,9 @@
* Allows to asynchronously dispatch onVmsMessageReceived events.
*/
private final static class VmsEventHandler extends Handler {
- /** Constants handled in the handler */
+ /**
+ * Constants handled in the handler
+ */
private static final int ON_RECEIVE_MESSAGE_EVENT = 0;
private static final int ON_AVAILABILITY_CHANGE_EVENT = 1;
@@ -140,16 +150,13 @@
* {@link com.android.car.VmsSubscriberService} are done through the {@link #mIListener}.
* Therefore, notifications from the {@link com.android.car.VmsSubscriberService} are received
* by the {@link #mIListener} and then forwarded to the {@link #mListener}.
- *
+ * <p>
* It is expected that this method is invoked just once during the lifetime of the object.
*
* @param listener subscriber listener that will handle onVmsMessageReceived events.
* @throws IllegalStateException if the listener was already set.
*/
public void setListener(VmsSubscriberClientListener listener) {
- if (DBG) {
- Log.d(TAG, "Setting listener.");
- }
synchronized (mListenerLock) {
if (mListener != null) {
throw new IllegalStateException("Listener is already configured.");
@@ -163,9 +170,6 @@
*/
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) {
@@ -184,20 +188,9 @@
* @throws IllegalStateException if the listener was not set via {@link #setListener}.
*/
public void subscribe(VmsLayer layer) throws CarNotConnectedException {
- if (DBG) {
- Log.d(TAG, "Subscribing to layer: " + layer);
- }
- VmsSubscriberClientListener listener;
- synchronized (mListenerLock) {
- listener = mListener;
- }
- if (listener == null) {
- Log.w(TAG, "subscribe: listener was not set, " +
- "setListener must be called first.");
- throw new IllegalStateException("Listener was not set.");
- }
+ verifySubscriptionIsAllowed();
try {
- mVmsSubscriberService.addVmsSubscriberClientListener(mIListener, layer);
+ mVmsSubscriberService.addVmsSubscriber(mIListener, layer);
VmsOperationRecorder.get().subscribe(layer);
} catch (RemoteException e) {
Log.e(TAG, "Could not connect: ", e);
@@ -207,21 +200,30 @@
}
}
- public void subscribeAll() throws CarNotConnectedException {
- if (DBG) {
- Log.d(TAG, "Subscribing passively to all data messages");
- }
- VmsSubscriberClientListener listener;
- synchronized (mListenerLock) {
- listener = mListener;
- }
- if (listener == null) {
- Log.w(TAG, "subscribe: listener was not set, " +
- "setListener must be called first.");
- throw new IllegalStateException("Listener was not set.");
- }
+ /**
+ * Subscribes to listen to the layer specified from the publisher specified.
+ *
+ * @param layer the layer to subscribe to.
+ * @param publisherId the publisher of the layer.
+ * @throws IllegalStateException if the listener was not set via {@link #setListener}.
+ */
+ public void subscribe(VmsLayer layer, int publisherId) throws CarNotConnectedException {
+ verifySubscriptionIsAllowed();
try {
- mVmsSubscriberService.addVmsSubscriberClientPassiveListener(mIListener);
+ mVmsSubscriberService.addVmsSubscriberToPublisher(mIListener, layer, publisherId);
+ VmsOperationRecorder.get().subscribe(layer, publisherId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not connect: ", e);
+ throw new CarNotConnectedException(e);
+ } catch (IllegalStateException ex) {
+ Car.checkCarNotConnectedExceptionFromCarService(ex);
+ }
+ }
+
+ public void subscribeAll() throws CarNotConnectedException {
+ verifySubscriptionIsAllowed();
+ try {
+ mVmsSubscriberService.addVmsSubscriberPassive(mIListener);
VmsOperationRecorder.get().subscribeAll();
} catch (RemoteException e) {
Log.e(TAG, "Could not connect: ", e);
@@ -238,20 +240,9 @@
* @throws IllegalStateException if the listener was not set via {@link #setListener}.
*/
public void unsubscribe(VmsLayer layer) {
- if (DBG) {
- Log.d(TAG, "Unsubscribing from layer: " + layer);
- }
- VmsSubscriberClientListener listener;
- synchronized (mListenerLock) {
- listener = mListener;
- }
- if (listener == null) {
- Log.w(TAG, "unsubscribe: listener was not set, " +
- "setListener must be called first.");
- throw new IllegalStateException("Listener was not set.");
- }
+ verifySubscriptionIsAllowed();
try {
- mVmsSubscriberService.removeVmsSubscriberClientListener(mIListener, layer);
+ mVmsSubscriberService.removeVmsSubscriber(mIListener, layer);
VmsOperationRecorder.get().unsubscribe(layer);
} catch (RemoteException e) {
Log.e(TAG, "Failed to unregister subscriber", e);
@@ -261,21 +252,29 @@
}
}
- public void unsubscribeAll() {
- if (DBG) {
- Log.d(TAG, "Unsubscribing passively from all data messages");
- }
- VmsSubscriberClientListener listener;
- synchronized (mListenerLock) {
- listener = mListener;
- }
- if (listener == null) {
- Log.w(TAG, "unsubscribeAll: listener was not set, " +
- "setListener must be called first.");
- throw new IllegalStateException("Listener was not set.");
- }
+ /**
+ * Unsubscribes from the layer/version specified.
+ *
+ * @param layer the layer to unsubscribe from.
+ * @param publisherId the pubisher of the layer.
+ * @throws IllegalStateException if the listener was not set via {@link #setListener}.
+ */
+ public void unsubscribe(VmsLayer layer, int publisherId) {
try {
- mVmsSubscriberService.removeVmsSubscriberClientPassiveListener(mIListener);
+ mVmsSubscriberService.removeVmsSubscriberToPublisher(
+ mIListener, layer, publisherId);
+ VmsOperationRecorder.get().unsubscribe(layer, publisherId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to unregister subscriber", e);
+ // ignore
+ } catch (IllegalStateException ex) {
+ Car.hideCarNotConnectedExceptionFromCarService(ex);
+ }
+ }
+
+ public void unsubscribeAll() {
+ try {
+ mVmsSubscriberService.removeVmsSubscriberPassive(mIListener);
VmsOperationRecorder.get().unsubscribeAll();
} catch (RemoteException e) {
Log.e(TAG, "Failed to unregister subscriber ", e);
@@ -286,30 +285,47 @@
}
private void dispatchOnReceiveMessage(VmsLayer layer, byte[] payload) {
- VmsSubscriberClientListener listener;
- synchronized (mListenerLock) {
- listener = mListener;
- }
+ VmsSubscriberClientListener listener = getListenerThreadSafe();
if (listener == null) {
- Log.e(TAG, "Listener died, not dispatching event.");
+ Log.e(TAG, "Cannot dispatch received message.");
return;
}
listener.onVmsMessageReceived(layer, payload);
}
private void dispatchOnAvailabilityChangeMessage(List<VmsLayer> availableLayers) {
- VmsSubscriberClientListener listener;
- synchronized (mListenerLock) {
- listener = mListener;
- }
+ VmsSubscriberClientListener listener = getListenerThreadSafe();
if (listener == null) {
- Log.e(TAG, "Listener died, not dispatching event.");
+ Log.e(TAG, "Cannot dispatch availability change message.");
return;
}
listener.onLayersAvailabilityChange(availableLayers);
}
- /** @hide */
+ private VmsSubscriberClientListener getListenerThreadSafe() {
+ VmsSubscriberClientListener listener;
+ synchronized (mListenerLock) {
+ listener = mListener;
+ }
+ if (listener == null) {
+ Log.e(TAG, "Listener not set.");
+ }
+ return listener;
+ }
+
+ /*
+ * Verifies that the subscriber is in a state where it is allowed to subscribe.
+ */
+ private void verifySubscriptionIsAllowed() {
+ VmsSubscriberClientListener listener = getListenerThreadSafe();
+ if (listener == null) {
+ throw new IllegalStateException("Cannot subscribe.");
+ }
+ }
+
+ /**
+ * @hide
+ */
@Override
public void onCarDisconnected() {
VmsSubscriberClientListener listener;
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index d919d8f..08fe6d0 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -89,7 +89,7 @@
android:id="@+id/delete_button"
style="@style/NumPadKeyButton"
android:gravity="center_vertical"
- android:src="@drawable/ic_backspace_24dp"
+ android:src="@drawable/ic_backspace_black_24dp"
android:clickable="true"
android:background="@drawable/ripple_drawable"
android:contentDescription="@string/keyboardview_keycode_delete"
diff --git a/service/src/com/android/car/CarAudioService.java b/service/src/com/android/car/CarAudioService.java
index d161883..3b871fa 100644
--- a/service/src/com/android/car/CarAudioService.java
+++ b/service/src/com/android/car/CarAudioService.java
@@ -429,6 +429,7 @@
if (audioPolicy != null) {
mAudioManager.unregisterAudioPolicyAsync(audioPolicy);
}
+ mVolumeService.release();
}
public synchronized void setAudioContextChangeListener(Looper looper,
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index c412b97..5b01bcf 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -28,9 +28,9 @@
import android.os.IBinder;
import android.os.Process;
import android.os.Trace;
-import android.util.BootTimingsTraceLog;
import android.util.Log;
import android.util.Slog;
+import android.util.TimingsTraceLog;
import com.android.car.cluster.InstrumentClusterService;
import com.android.car.hal.VehicleHal;
import com.android.car.internal.FeatureConfiguration;
@@ -81,7 +81,7 @@
private static final String TAG = "ICarImpl";
private static final String VHAL_TIMING_TAG = "VehicleHalTiming";
- private static final BootTimingsTraceLog mBootTiming = new BootTimingsTraceLog(VHAL_TIMING_TAG,
+ private static final TimingsTraceLog mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG,
Trace.TRACE_TAG_HAL);
/** Test only service. Populate it only when necessary. */
diff --git a/service/src/com/android/car/VmsSubscriberService.java b/service/src/com/android/car/VmsSubscriberService.java
index 85b312d..f5787b5 100644
--- a/service/src/com/android/car/VmsSubscriberService.java
+++ b/service/src/com/android/car/VmsSubscriberService.java
@@ -219,7 +219,7 @@
// Implements IVmsService interface.
@Override
- public void addVmsSubscriberClientListener(IVmsSubscriberClient subscriber, VmsLayer layer) {
+ public void addVmsSubscriber(IVmsSubscriberClient subscriber, VmsLayer layer) {
synchronized (mSubscriberServiceLock) {
// Add the subscriber so it can subscribe.
mMessageReceivedManager.add(subscriber);
@@ -230,7 +230,7 @@
}
@Override
- public void removeVmsSubscriberClientListener(IVmsSubscriberClient subscriber, VmsLayer layer) {
+ public void removeVmsSubscriber(IVmsSubscriberClient subscriber, VmsLayer layer) {
synchronized (mSubscriberServiceLock) {
// Remove the subscription.
mHal.removeSubscription(subscriber, layer);
@@ -243,7 +243,35 @@
}
@Override
- public void addVmsSubscriberClientPassiveListener(IVmsSubscriberClient subscriber) {
+ public void addVmsSubscriberToPublisher(IVmsSubscriberClient subscriber,
+ VmsLayer layer,
+ int publisherId) {
+ synchronized (mSubscriberServiceLock) {
+ // Add the subscriber so it can subscribe.
+ mMessageReceivedManager.add(subscriber);
+
+ // Add the subscription for the layer.
+ mHal.addSubscription(subscriber, layer, publisherId);
+ }
+ }
+
+ @Override
+ public void removeVmsSubscriberToPublisher(IVmsSubscriberClient subscriber,
+ VmsLayer layer,
+ int publisherId) {
+ synchronized (mSubscriberServiceLock) {
+ // Remove the subscription.
+ mHal.removeSubscription(subscriber, layer, publisherId);
+
+ // Remove the subscriber if it has no more subscriptions.
+ if (!mHal.containsSubscriber(subscriber)) {
+ mMessageReceivedManager.remove(subscriber);
+ }
+ }
+ }
+
+ @Override
+ public void addVmsSubscriberPassive(IVmsSubscriberClient subscriber) {
synchronized (mSubscriberServiceLock) {
mMessageReceivedManager.add(subscriber);
mHal.addSubscription(subscriber);
@@ -251,7 +279,7 @@
}
@Override
- public void removeVmsSubscriberClientPassiveListener(IVmsSubscriberClient subscriber) {
+ public void removeVmsSubscriberPassive(IVmsSubscriberClient subscriber) {
synchronized (mSubscriberServiceLock) {
// Remove the subscription.
mHal.removeSubscription(subscriber);
@@ -279,7 +307,7 @@
// Implements VmsHalSubscriberListener interface
@Override
public void onDataMessage(VmsLayer layer, int publisherId, byte[] payload) {
- if(DBG) {
+ if (DBG) {
Log.d(TAG, "Publishing a message for layer: " + layer);
}
@@ -299,7 +327,7 @@
@Override
public void onLayersAvaiabilityChange(List<VmsAssociatedLayer> availableLayers) {
- if(DBG) {
+ if (DBG) {
Log.d(TAG, "Publishing layers availability change: " + availableLayers);
}
diff --git a/service/src/com/android/car/hal/VmsHalService.java b/service/src/com/android/car/hal/VmsHalService.java
index 1defac1..7ff407f 100644
--- a/service/src/com/android/car/hal/VmsHalService.java
+++ b/service/src/com/android/car/hal/VmsHalService.java
@@ -144,7 +144,8 @@
mRouting.addSubscription(listener, layer);
}
if (firstSubscriptionForLayer) {
- notifyPublishers(layer, true);
+ notifyHalPublishers(layer, true);
+ notifyClientPublishers();
}
}
@@ -163,7 +164,8 @@
layerHasSubscribers = mRouting.hasLayerSubscriptions(layer);
}
if (!layerHasSubscribers) {
- notifyPublishers(layer, false);
+ notifyHalPublishers(layer, false);
+ notifyClientPublishers();
}
}
@@ -179,6 +181,44 @@
}
}
+ public void addSubscription(IVmsSubscriberClient listener, VmsLayer layer, int publisherId) {
+ boolean firstSubscriptionForLayer = false;
+ synchronized (mLock) {
+ // Check if publishers need to be notified about this change in subscriptions.
+ firstSubscriptionForLayer = !(mRouting.hasLayerSubscriptions(layer) ||
+ mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId));
+
+ // Add the listeners subscription to the layer
+ mRouting.addSubscription(listener, layer, publisherId);
+ }
+ if (firstSubscriptionForLayer) {
+ notifyHalPublishers(layer, true);
+ notifyClientPublishers();
+ }
+ }
+
+ public void removeSubscription(IVmsSubscriberClient listener, VmsLayer layer, int publisherId) {
+ boolean layerHasSubscribers = true;
+ synchronized (mLock) {
+ if (!mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId)) {
+ Log.i(TAG, "Trying to remove a layer with no subscription: " +
+ layer + ", publisher ID:" + publisherId);
+ return;
+ }
+
+ // Remove the listeners subscription to the layer
+ mRouting.removeSubscription(listener, layer, publisherId);
+
+ // Check if publishers need to be notified about this change in subscriptions.
+ layerHasSubscribers = mRouting.hasLayerSubscriptions(layer) ||
+ mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId);
+ }
+ if (!layerHasSubscribers) {
+ notifyHalPublishers(layer, false);
+ notifyClientPublishers();
+ }
+ }
+
public void removeDeadSubscriber(IVmsSubscriberClient listener) {
synchronized (mLock) {
mRouting.removeDeadSubscriber(listener);
@@ -234,7 +274,7 @@
}
}
- public void addHalSubscription(VmsLayer layer) {
+ private void addHalSubscription(VmsLayer layer) {
boolean firstSubscriptionForLayer = true;
synchronized (mLock) {
// Check if publishers need to be notified about this change in subscriptions.
@@ -244,11 +284,28 @@
mRouting.addHalSubscription(layer);
}
if (firstSubscriptionForLayer) {
- notifyPublishers(layer, true);
+ notifyHalPublishers(layer, true);
+ notifyClientPublishers();
}
}
- public void removeHalSubscription(VmsLayer layer) {
+ private void addHalSubscriptionToPublisher(VmsLayer layer, int publisherId) {
+ boolean firstSubscriptionForLayer = true;
+ synchronized (mLock) {
+ // Check if publishers need to be notified about this change in subscriptions.
+ firstSubscriptionForLayer = !(mRouting.hasLayerSubscriptions(layer) ||
+ mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId));
+
+ // Add the listeners subscription to the layer
+ mRouting.addHalSubscriptionToPublisher(layer, publisherId);
+ }
+ if (firstSubscriptionForLayer) {
+ notifyHalPublishers(layer, publisherId, true);
+ notifyClientPublishers();
+ }
+ }
+
+ private void removeHalSubscription(VmsLayer layer) {
boolean layerHasSubscribers = true;
synchronized (mLock) {
if (!mRouting.hasLayerSubscriptions(layer)) {
@@ -263,7 +320,29 @@
layerHasSubscribers = mRouting.hasLayerSubscriptions(layer);
}
if (!layerHasSubscribers) {
- notifyPublishers(layer, false);
+ notifyHalPublishers(layer, false);
+ notifyClientPublishers();
+ }
+ }
+
+ public void removeHalSubscriptionFromPublisher(VmsLayer layer, int publisherId) {
+ boolean layerHasSubscribers = true;
+ synchronized (mLock) {
+ if (!mRouting.hasLayerSubscriptions(layer)) {
+ Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
+ return;
+ }
+
+ // Remove the listeners subscription to the layer
+ mRouting.removeHalSubscriptionToPublisher(layer, publisherId);
+
+ // Check if publishers need to be notified about this change in subscriptions.
+ layerHasSubscribers = mRouting.hasLayerSubscriptions(layer) ||
+ mRouting.hasLayerFromPublisherSubscriptions(layer, publisherId);
+ }
+ if (!layerHasSubscribers) {
+ notifyHalPublishers(layer, publisherId, false);
+ notifyClientPublishers();
}
}
@@ -297,10 +376,17 @@
* @param layer layer which is being subscribed to or unsubscribed from.
* @param hasSubscribers indicates if the notification is for subscription or unsubscription.
*/
- private void notifyPublishers(VmsLayer layer, boolean hasSubscribers) {
+ private void notifyHalPublishers(VmsLayer layer, boolean hasSubscribers) {
// notify the HAL
setSubscriptionRequest(layer, hasSubscribers);
+ }
+ private void notifyHalPublishers(VmsLayer layer, int publisherId, boolean hasSubscribers) {
+ // notify the HAL
+ setSubscriptionToPublisherRequest(layer, publisherId, hasSubscribers);
+ }
+
+ private void notifyClientPublishers() {
// Notify the App publishers
for (VmsHalPublisherListener listener : mPublisherListeners) {
// Besides the list of layers, also a timestamp is provided to the clients.
@@ -390,6 +476,12 @@
case VmsMessageType.UNSUBSCRIBE:
handleUnsubscribeEvent(vec);
break;
+ case VmsMessageType.SUBSCRIBE_TO_PUBLISHER:
+ handleSubscribeToPublisherEvent(vec);
+ break;
+ case VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER:
+ handleUnsubscribeFromPublisherEvent(vec);
+ break;
case VmsMessageType.OFFERING:
handleOfferingEvent(vec);
break;
@@ -450,6 +542,7 @@
* <li>Message type.
* <li>Layer id.
* <li>Layer version.
+ * <li>Layer subtype.
* </ul>
*/
private void handleSubscribeEvent(List<Integer> integerValues) {
@@ -461,6 +554,27 @@
}
/**
+ * Subscribe message format:
+ * <ul>
+ * <li>Message type.
+ * <li>Layer id.
+ * <li>Layer version.
+ * <li>Layer subtype.
+ * <li>Publisher ID
+ * </ul>
+ */
+ private void handleSubscribeToPublisherEvent(List<Integer> integerValues) {
+ VmsLayer vmsLayer = parseVmsLayerFromSimpleMessageIntegerValues(integerValues);
+ if (DBG) {
+ Log.d(TAG, "Handling a subscribe event for Layer: " + vmsLayer);
+ }
+ int publisherId =
+ //integerValues.get(/*VmsSimpleMessageIntegerValuesIndex.VMS_LAYER_SUB_TYPE*/0);
+ integerValues.get(VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.PUBLISHER_ID);
+ addHalSubscriptionToPublisher(vmsLayer, publisherId);
+ }
+
+ /**
* Unsubscribe message format:
* <ul>
* <li>Message type.
@@ -476,6 +590,25 @@
removeHalSubscription(vmsLayer);
}
+ /**
+ * Unsubscribe message format:
+ * <ul>
+ * <li>Message type.
+ * <li>Layer id.
+ * <li>Layer version.
+ * </ul>
+ */
+ private void handleUnsubscribeFromPublisherEvent(List<Integer> integerValues) {
+ VmsLayer vmsLayer = parseVmsLayerFromSimpleMessageIntegerValues(integerValues);
+ int publisherId =
+ //integerValues.get(/*VmsSimpleMessageIntegerValuesIndex.VMS_LAYER_SUB_TYPE*/0);
+ integerValues.get(VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.PUBLISHER_ID);
+ if (DBG) {
+ Log.d(TAG, "Handling an unsubscribe event for Layer: " + vmsLayer);
+ }
+ removeHalSubscriptionFromPublisher(vmsLayer, publisherId);
+ }
+
private static int NUM_INTEGERS_IN_VMS_LAYER = 3;
private VmsLayer parseVmsLayerFromIndex(List<Integer> integerValues, int index) {
@@ -622,6 +755,17 @@
return setPropertyValue(vehiclePropertyValue);
}
+ public boolean setSubscriptionToPublisherRequest(VmsLayer layer,
+ int publisherId,
+ boolean hasSubscribers) {
+ VehiclePropValue vehiclePropertyValue = toTypedVmsVehiclePropValueWithLayer(
+ hasSubscribers ?
+ VmsMessageType.SUBSCRIBE_TO_PUBLISHER :
+ VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER, layer);
+ vehiclePropertyValue.value.int32Values.add(publisherId);
+ return setPropertyValue(vehiclePropertyValue);
+ }
+
public boolean setDataMessage(VmsLayer layer, byte[] payload) {
VehiclePropValue vehiclePropertyValue =
toTypedVmsVehiclePropValueWithLayer(VmsMessageType.DATA, layer);
diff --git a/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java b/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
index a45d9df..dc42787 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
+++ b/tests/carservice_test/src/com/android/car/test/VmsOperationRecorderTest.java
@@ -33,7 +33,9 @@
@MediumTest
public class VmsOperationRecorderTest extends TestCase {
- /** Capture messages that VmsOperationRecorder.Writer would normally pass to Log.d(...). */
+ /**
+ * Capture messages that VmsOperationRecorder.Writer would normally pass to Log.d(...).
+ */
class TestWriter extends VmsOperationRecorder.Writer {
public String mMsg;
@@ -157,6 +159,18 @@
+ "{'layer':{'id':3,'version':4,'subtype':5}}]}}");
}
+ public void testSubscribeToPublisher() throws Exception {
+ mRecorder.subscribe(layer1, 99);
+ assertJsonMsgEquals(
+ "{'subscribe':{'publisherId':99, 'layer':{'id':1,'version':2,'subtype':3}}}");
+ }
+
+ public void testUnsubscribeToPublisher() throws Exception {
+ mRecorder.unsubscribe(layer1, 99);
+ assertJsonMsgEquals(
+ "{'unsubscribe':{'publisherId':99, 'layer':{'id':1,'version':2,'subtype':3}}}}");
+ }
+
private void assertJsonMsgEquals(String expectJson) throws Exception {
// Escaping double quotes in a JSON string is really noisy. The test data uses single
// quotes instead, which gets replaced here.
diff --git a/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java b/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
index b8d904a..c8dfb9c 100644
--- a/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/test/VmsSubscriberManagerTest.java
@@ -16,6 +16,8 @@
package com.android.car.test;
+import static org.junit.Assume.assumeTrue;
+
import android.car.Car;
import android.car.VehicleAreaType;
import android.car.annotation.FutureFeature;
@@ -47,6 +49,7 @@
public class VmsSubscriberManagerTest extends MockedCarTestBase {
private static final String TAG = "VmsSubscriberManagerTest";
private static final int PUBLISHER_ID = 17;
+ private static final int WRONG_PUBLISHER_ID = 26;
private static final Set<Integer> PUBLISHERS_LIST = new HashSet<Integer>(Arrays.asList(PUBLISHER_ID));
private static final int SUBSCRIPTION_LAYER_ID = 2;
@@ -113,7 +116,7 @@
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
public void testSubscribe() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestListener listener = new TestListener();
@@ -141,9 +144,153 @@
assertTrue(Arrays.equals(expectedPayload, listener.getPayload()));
}
+
+ // Test injecting a value in the HAL and verifying it propagates to a subscriber.
+ public void testSubscribeToPublisher() throws Exception {
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
+ VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ TestListener listener = new TestListener();
+ vmsSubscriberManager.setListener(listener);
+ vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
+
+ // Inject a value and wait for its callback in TestListener.onVmsMessageReceived.
+ VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build();
+ v.value.int32Values.add(VmsMessageType.DATA); // MessageType
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
+ v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUB_TYPE);
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
+ v.value.int32Values.add(WRONG_PUBLISHER_ID);
+ v.value.bytes.add((byte) 0xa);
+ v.value.bytes.add((byte) 0xb);
+ assertEquals(0, mSubscriberSemaphore.availablePermits());
+
+ getMockedVehicleHal().injectEvent(v);
+
+ assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ }
+
+ // Test injecting a value in the HAL and verifying it propagates to a subscriber.
+ public void testSubscribeFromPublisher() throws Exception {
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
+ VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ TestListener listener = new TestListener();
+ vmsSubscriberManager.setListener(listener);
+ vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
+
+ // Inject a value and wait for its callback in TestListener.onVmsMessageReceived.
+ VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build();
+ v.value.int32Values.add(VmsMessageType.DATA); // MessageType
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
+ v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUB_TYPE); //<-
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
+ v.value.int32Values.add(PUBLISHER_ID);
+ v.value.bytes.add((byte) 0xa);
+ v.value.bytes.add((byte) 0xb);
+ assertEquals(0, mSubscriberSemaphore.availablePermits());
+
+ getMockedVehicleHal().injectEvent(v);
+ assertTrue(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ assertEquals(SUBSCRIPTION_LAYER, listener.getLayer());
+ byte[] expectedPayload = {(byte) 0xa, (byte) 0xb};
+ assertTrue(Arrays.equals(expectedPayload, listener.getPayload()));
+ }
+
+ // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
+ public void testUnsubscribe() throws Exception {
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
+ VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ TestListener listener = new TestListener();
+ vmsSubscriberManager.setListener(listener);
+ vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER);
+ vmsSubscriberManager.unsubscribe(SUBSCRIPTION_LAYER);
+
+ // Inject a value and wait for its callback in TestListener.onVmsMessageReceived.
+ VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build();
+ v.value.int32Values.add(VmsMessageType.DATA); // MessageType
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
+ v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUB_TYPE);
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
+ v.value.int32Values.add(PUBLISHER_ID);
+ v.value.bytes.add((byte) 0xa);
+ v.value.bytes.add((byte) 0xb);
+ assertEquals(0, mSubscriberSemaphore.availablePermits());
+
+ getMockedVehicleHal().injectEvent(v);
+ assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ }
+
+ // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
+ public void testSubscribeFromWrongPublisher() throws Exception {
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
+ VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ TestListener listener = new TestListener();
+ vmsSubscriberManager.setListener(listener);
+ vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
+
+ // Inject a value and wait for its callback in TestListener.onVmsMessageReceived.
+ VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build();
+ v.value.int32Values.add(VmsMessageType.DATA); // MessageType
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
+ v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUB_TYPE);
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
+ v.value.int32Values.add(WRONG_PUBLISHER_ID);
+ v.value.bytes.add((byte) 0xa);
+ v.value.bytes.add((byte) 0xb);
+ assertEquals(0, mSubscriberSemaphore.availablePermits());
+
+ getMockedVehicleHal().injectEvent(v);
+ assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ }
+
+ // Test injecting a value in the HAL and verifying it does not propagate to a subscriber.
+ public void testUnsubscribeFromPublisher() throws Exception {
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
+ VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
+ Car.VMS_SUBSCRIBER_SERVICE);
+ TestListener listener = new TestListener();
+ vmsSubscriberManager.setListener(listener);
+ vmsSubscriberManager.subscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
+ vmsSubscriberManager.unsubscribe(SUBSCRIPTION_LAYER, PUBLISHER_ID);
+
+ // Inject a value and wait for its callback in TestListener.onVmsMessageReceived.
+ VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
+ .setAreaId(VehicleAreaType.VEHICLE_AREA_TYPE_NONE)
+ .setTimestamp(SystemClock.elapsedRealtimeNanos())
+ .build();
+ v.value.int32Values.add(VmsMessageType.DATA); // MessageType
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_ID);
+ v.value.int32Values.add(MOCK_PUBLISHER_LAYER_SUB_TYPE);
+ v.value.int32Values.add(SUBSCRIPTION_LAYER_VERSION);
+ v.value.int32Values.add(PUBLISHER_ID);
+ v.value.bytes.add((byte) 0xa);
+ v.value.bytes.add((byte) 0xb);
+ assertEquals(0, mSubscriberSemaphore.availablePermits());
+
+ getMockedVehicleHal().injectEvent(v);
+ assertFalse(mSubscriberSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ }
+
+
+
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
public void testSubscribeAll() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestListener listener = new TestListener();
@@ -173,7 +320,7 @@
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
public void testSimpleAvailableLayers() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestListener listener = new TestListener();
@@ -219,7 +366,7 @@
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
public void testComplexAvailableLayers() throws Exception {
- if (!VmsTestUtils.canRunTest(TAG)) return;
+ assumeTrue(VmsTestUtils.canRunTest(TAG));
VmsSubscriberManager vmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
TestListener listener = new TestListener();
diff --git a/tools/io_analysis/check_file_read.py b/tools/io_analysis/check_file_read.py
index 06b4f43..32c687e 100644
--- a/tools/io_analysis/check_file_read.py
+++ b/tools/io_analysis/check_file_read.py
@@ -42,11 +42,13 @@
self.processes.append((open_time, process_name, flags))
self.reads = []
self.total_reads = 0
+ self.total_blocks = 0
self.total_open = 1
self.blocks = {}
self.total_rereads = 0
self.read_size_histogram = {} #key: read size, value: occurrence
self.single_block_reads = {} # process name, occurrence
+ self.fresh_reads = [] # (offset, size)
def add_open(self, open_time, process_name, flags):
self.processes.append((open_time, process_name, flags))
@@ -55,9 +57,12 @@
def add_read(self, time, offset, size, process_name):
self.reads.append((time, offset, size, process_name))
self.total_reads += size
+ already_read = True
for i in range(offset, offset + size):
if not self.blocks.get(i):
self.blocks[i] = 1
+ already_read = False
+ self.total_blocks += 1
else:
self.blocks[i] += 1
self.total_rereads += 1
@@ -65,6 +70,8 @@
self.read_size_histogram[size] = 1
else:
self.read_size_histogram[size] += 1
+ if not already_read:
+ self.fresh_reads.append((offset, size))
if size == 1:
if not self.single_block_reads.get(process_name):
self.single_block_reads[process_name] = 1
@@ -72,8 +79,9 @@
self.single_block_reads[process_name] += 1
def dump(self):
- print " filename %s, total reads %d, total open %d total rereads %d inode %s" \
- % (self.file_name, self.total_reads, self.total_open, self.total_rereads, self.inode)
+ print " filename %s, total reads %d, total open %d total rereads %d inode %s blocks %d" \
+ % (self.file_name, self.total_reads, self.total_open, self.total_rereads, self.inode, \
+ self.total_blocks)
process_names = []
for opener in self.processes:
process_names.append(opener[1])
@@ -84,6 +92,7 @@
if len(self.single_block_reads) > 1 and len(self.reads) > 1:
print " Single block reads:", collections.OrderedDict( \
sorted(self.single_block_reads.items(), key = lambda item: item[1], reverse = True))
+ print " Fresh reads:", self.fresh_reads
class Trace:
def __init__(self):
@@ -150,7 +159,7 @@
def dump_partition(self, partition_name, files):
- print "**Dump partition:", partition_name, "toal number of files:", len(files)
+ print "**Dump partition:", partition_name, "total number of files:", len(files)
total_reads = 0
total_rereads = 0
vs = files.values()