Merge "Fixed null pointer exception on mSupportedAreas." into qt-dev
diff --git a/car-lib/src/android/car/drivingstate/CarUxRestrictionsConfiguration.java b/car-lib/src/android/car/drivingstate/CarUxRestrictionsConfiguration.java
index 4ca54a7..5806aa4 100644
--- a/car-lib/src/android/car/drivingstate/CarUxRestrictionsConfiguration.java
+++ b/car-lib/src/android/car/drivingstate/CarUxRestrictionsConfiguration.java
@@ -826,6 +826,9 @@
public SpeedRange(@FloatRange(from = 0.0) float minSpeed,
@FloatRange(from = 0.0) float maxSpeed) {
+ if (Float.compare(minSpeed, 0) < 0 || Float.compare(maxSpeed, 0) < 0) {
+ throw new IllegalArgumentException("Speed cannot be negative.");
+ }
if (minSpeed == MAX_SPEED) {
throw new IllegalArgumentException("Min speed cannot be MAX_SPEED.");
}
diff --git a/car-lib/src/android/car/drivingstate/CarUxRestrictionsManager.java b/car-lib/src/android/car/drivingstate/CarUxRestrictionsManager.java
index 4848e99..6ba3f97 100644
--- a/car-lib/src/android/car/drivingstate/CarUxRestrictionsManager.java
+++ b/car-lib/src/android/car/drivingstate/CarUxRestrictionsManager.java
@@ -30,6 +30,8 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -78,10 +80,10 @@
private final Context mContext;
private final ICarUxRestrictionsManager mUxRService;
private final EventCallbackHandler mEventCallbackHandler;
+ @GuardedBy("this")
private OnUxRestrictionsChangedListener mUxRListener;
private CarUxRestrictionsChangeListenerToService mListenerToService;
-
/** @hide */
public CarUxRestrictionsManager(IBinder service, Context context, Handler handler) {
mContext = context;
@@ -91,9 +93,11 @@
/** @hide */
@Override
- public synchronized void onCarDisconnected() {
+ public void onCarDisconnected() {
mListenerToService = null;
- mUxRListener = null;
+ synchronized (this) {
+ mUxRListener = null;
+ }
}
/**
@@ -118,21 +122,18 @@
*
* @param listener {@link OnUxRestrictionsChangedListener}
*/
- public synchronized void registerListener(@NonNull OnUxRestrictionsChangedListener listener) {
- if (listener == null) {
- if (VDBG) {
- Log.v(TAG, "registerListener(): null listener");
+ public void registerListener(@NonNull OnUxRestrictionsChangedListener listener) {
+ synchronized (this) {
+ // Check if the listener has been already registered.
+ if (mUxRListener != null) {
+ if (DBG) {
+ Log.d(TAG, "Listener already registered listener");
+ }
+ return;
}
- throw new IllegalArgumentException("Listener is null");
+ mUxRListener = listener;
}
- // Check if the listener has been already registered.
- if (mUxRListener != null) {
- if (DBG) {
- Log.d(TAG, "Listener already registered listener");
- }
- return;
- }
- mUxRListener = listener;
+
try {
if (mListenerToService == null) {
mListenerToService = new CarUxRestrictionsChangeListenerToService(this);
@@ -147,16 +148,18 @@
/**
* Unregister the registered {@link OnUxRestrictionsChangedListener}
*/
- public synchronized void unregisterListener() {
- if (mUxRListener == null) {
- if (DBG) {
- Log.d(TAG, "Listener was not previously registered");
+ public void unregisterListener() {
+ synchronized (this) {
+ if (mUxRListener == null) {
+ if (DBG) {
+ Log.d(TAG, "Listener was not previously registered");
+ }
+ return;
}
- return;
+ mUxRListener = null;
}
try {
mUxRService.unregisterUxRestrictionsChangeListener(mListenerToService);
- mUxRListener = null;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -220,7 +223,7 @@
* @hide
*/
@RequiresPermission(value = Car.PERMISSION_CAR_UX_RESTRICTIONS_CONFIGURATION)
- public synchronized boolean saveUxRestrictionsConfigurationForNextBoot(
+ public boolean saveUxRestrictionsConfigurationForNextBoot(
CarUxRestrictionsConfiguration config) {
try {
return mUxRService.saveUxRestrictionsConfigurationForNextBoot(config);
@@ -240,7 +243,7 @@
*/
@Nullable
@RequiresPermission(value = Car.PERMISSION_CAR_UX_RESTRICTIONS_CONFIGURATION)
- public synchronized CarUxRestrictionsConfiguration getStagedConfig() {
+ public CarUxRestrictionsConfiguration getStagedConfig() {
try {
return mUxRService.getStagedConfig();
} catch (RemoteException e) {
@@ -256,7 +259,7 @@
* @hide
*/
@RequiresPermission(value = Car.PERMISSION_CAR_UX_RESTRICTIONS_CONFIGURATION)
- public synchronized CarUxRestrictionsConfiguration getConfig() {
+ public CarUxRestrictionsConfiguration getConfig() {
try {
return mUxRService.getConfig();
} catch (RemoteException e) {
@@ -331,7 +334,6 @@
mgr.dispatchUxRChangeToClient((CarUxRestrictions) msg.obj);
}
}
-
}
/**
@@ -344,12 +346,10 @@
if (restrictionInfo == null) {
return;
}
- OnUxRestrictionsChangedListener listener;
synchronized (this) {
- listener = mUxRListener;
- }
- if (listener != null) {
- listener.onUxRestrictionsChanged(restrictionInfo);
+ if (mUxRListener != null) {
+ mUxRListener.onUxRestrictionsChanged(restrictionInfo);
+ }
}
}
}
diff --git a/car_product/build/car.mk b/car_product/build/car.mk
index eb9bab3..3b40292 100644
--- a/car_product/build/car.mk
+++ b/car_product/build/car.mk
@@ -53,7 +53,7 @@
PRODUCT_PROPERTY_OVERRIDES += \
persist.bluetooth.enablenewavrcp=false \
ro.carrier=unknown \
- ro.fw.multiuser.headless_system_user=true
+ ro.fw.mu.headless_system_user=true
# Overlay for Google network and fused location providers
$(call inherit-product, device/sample/products/location_overlay.mk)
diff --git a/service/Android.mk b/service/Android.mk
index a9d0e0b..f16877e 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -53,6 +53,7 @@
car-frameworks-service \
car-systemtest \
com.android.car.procfsinspector-client \
+ blestream-protos \
LOCAL_STATIC_ANDROID_LIBRARIES := \
SettingsLib \
@@ -88,6 +89,7 @@
vehicle-hal-support-lib \
car-systemtest \
com.android.car.procfsinspector-client \
+ blestream-protos \
LOCAL_STATIC_ANDROID_LIBRARIES := \
SettingsLib \
diff --git a/service/proto/Android.bp b/service/proto/Android.bp
new file mode 100644
index 0000000..8d500ea
--- /dev/null
+++ b/service/proto/Android.bp
@@ -0,0 +1,11 @@
+java_library_static {
+ name: "blestream-protos",
+ host_supported: true,
+ proto: {
+ type: "lite",
+ },
+ srcs: ["*.proto"],
+ no_framework_libs: true,
+ jarjar_rules: "jarjar-rules.txt",
+ sdk_version: "28",
+}
diff --git a/service/proto/BLEHandshake.proto b/service/proto/BLEHandshake.proto
new file mode 100644
index 0000000..26f5783
--- /dev/null
+++ b/service/proto/BLEHandshake.proto
@@ -0,0 +1,14 @@
+syntax = "proto3";
+
+package com.android.car.trust.BLEHandshake;
+
+option java_package = "com.android.car.trust";
+option java_outer_classname = "BLEHandshake";
+
+message VersionExchange {
+ // Required.
+ int32 minSupportedVersion = 1;
+
+ // Required.
+ int32 maxSupportedVersion = 2;
+}
\ No newline at end of file
diff --git a/service/proto/BLEStream.proto b/service/proto/BLEStream.proto
new file mode 100644
index 0000000..c0a1817
--- /dev/null
+++ b/service/proto/BLEStream.proto
@@ -0,0 +1,23 @@
+syntax = "proto3";
+
+package com.android.car.trust.BLEStream;
+
+option java_package = "com.android.car.trust";
+option java_outer_classname = "BLEStream";
+
+message BLEMessage {
+ // Required.
+ int32 version = 1;
+
+ // Required.
+ int32 operation = 2;
+
+ // Required.
+ int32 packet_number = 3;
+
+ // Required.
+ int32 total_packets = 4;
+
+ // Required.
+ bytes payload = 5;
+}
diff --git a/service/proto/jarjar-rules.txt b/service/proto/jarjar-rules.txt
new file mode 100644
index 0000000..c06c995
--- /dev/null
+++ b/service/proto/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.google.protobuf.** com.android.car.trust.protobuf.@1
\ No newline at end of file
diff --git a/service/res/values/attrs.xml b/service/res/values/attrs.xml
index be20c0f..483c7e1 100644
--- a/service/res/values/attrs.xml
+++ b/service/res/values/attrs.xml
@@ -92,6 +92,14 @@
<flag name="no_voice_transcription" value="256"/>
<flag name="fully_restricted" value="511"/>
</attr>
+ <!-- UX restrictions service supports returning different sets of UX restrictions for
+ the same driving state, through configurations for each "mode". -->
+ <attr name="mode">
+ <!-- Default mode. -->
+ <flag name="baseline" value="0"/>
+ <!-- Mode for passenger to interact with system. -->
+ <flag name="passenger" value="1"/>
+ </attr>
</declare-styleable>
<!-- 2. Some of UX restrictions can be parametrized. -->
diff --git a/service/src/com/android/car/CarUxRestrictionsConfigurationXmlParser.java b/service/src/com/android/car/CarUxRestrictionsConfigurationXmlParser.java
index 95bcb2c..eec55c5 100644
--- a/service/src/com/android/car/CarUxRestrictionsConfigurationXmlParser.java
+++ b/service/src/com/android/car/CarUxRestrictionsConfigurationXmlParser.java
@@ -16,17 +16,20 @@
package com.android.car;
+import static android.car.drivingstate.CarUxRestrictionsManager.UX_RESTRICTION_MODE_BASELINE;
+
import android.annotation.Nullable;
import android.annotation.XmlRes;
import android.car.drivingstate.CarDrivingStateEvent;
import android.car.drivingstate.CarUxRestrictions;
import android.car.drivingstate.CarUxRestrictionsConfiguration;
+import android.car.drivingstate.CarUxRestrictionsConfiguration.Builder;
+import android.car.drivingstate.CarUxRestrictionsConfiguration.DrivingStateRestrictions;
import android.content.Context;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Pair;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParserException;
@@ -160,19 +163,12 @@
// 1. Get the driving state attributes: driving state and speed range
TypedArray a = mContext.getResources().obtainAttributes(attrs,
R.styleable.UxRestrictions_DrivingState);
- int drivingState = a
- .getInt(R.styleable.UxRestrictions_DrivingState_state,
- CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
- float minSpeed = a
- .getFloat(
- R.styleable
- .UxRestrictions_DrivingState_minSpeed,
- INVALID_SPEED);
- float maxSpeed = a
- .getFloat(
- R.styleable
- .UxRestrictions_DrivingState_maxSpeed,
- INVALID_SPEED);
+ int drivingState = a.getInt(R.styleable.UxRestrictions_DrivingState_state,
+ CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
+ float minSpeed = a.getFloat(R.styleable.UxRestrictions_DrivingState_minSpeed,
+ INVALID_SPEED);
+ float maxSpeed = a.getFloat(R.styleable.UxRestrictions_DrivingState_maxSpeed,
+ Builder.SpeedRange.MAX_SPEED);
a.recycle();
// 2. Traverse to the <Restrictions> tag
@@ -182,7 +178,42 @@
}
// 3. Parse the restrictions for this driving state
- Pair<Boolean, Integer> restrictions = parseRestrictions(parser, attrs);
+ Builder.SpeedRange speedRange = parseSpeedRange(minSpeed, maxSpeed);
+ if (!parseAllRestrictions(parser, attrs, drivingState, speedRange)) {
+ Log.e(TAG, "Could not parse restrictions for driving state:" + drivingState);
+ return false;
+ }
+ }
+ parser.next();
+ }
+ return true;
+ }
+
+ /**
+ * Parses all <restrictions> tags nested with <drivingState> tag.
+ */
+ private boolean parseAllRestrictions(XmlResourceParser parser, AttributeSet attrs,
+ int drivingState, Builder.SpeedRange speedRange)
+ throws IOException, XmlPullParserException {
+ if (parser == null || attrs == null) {
+ Log.e(TAG, "Invalid arguments");
+ return false;
+ }
+ // The parser should be at the <Restrictions> tag at this point.
+ if (!RESTRICTIONS.equals(parser.getName())) {
+ Log.e(TAG, "Parser not at Restrictions element: " + parser.getName());
+ return false;
+ }
+ while (RESTRICTIONS.equals(parser.getName())) {
+ if (parser.getEventType() == XmlResourceParser.START_TAG) {
+ // Parse one restrictions tag.
+ DrivingStateRestrictions restrictions = parseRestrictions(parser, attrs);
+ if (restrictions == null) {
+ Log.e(TAG, "");
+ return false;
+ }
+ restrictions.setSpeedRange(speedRange);
+
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Map " + drivingState + " : " + restrictions);
}
@@ -190,8 +221,8 @@
// Update the builder if the driving state and restrictions info are valid.
if (drivingState != CarDrivingStateEvent.DRIVING_STATE_UNKNOWN
&& restrictions != null) {
- addToRestrictions(drivingState, minSpeed, maxSpeed, restrictions.first,
- restrictions.second);
+
+ mConfigBuilder.setUxRestrictions(drivingState, restrictions);
}
}
parser.next();
@@ -204,15 +235,16 @@
* for the enclosing driving state.
*/
@Nullable
- private Pair<Boolean, Integer> parseRestrictions(XmlResourceParser parser, AttributeSet attrs)
+ private DrivingStateRestrictions parseRestrictions(XmlResourceParser parser, AttributeSet attrs)
throws IOException, XmlPullParserException {
- int restrictions = UX_RESTRICTIONS_UNKNOWN;
- boolean requiresOpt = true;
if (parser == null || attrs == null) {
Log.e(TAG, "Invalid Arguments");
return null;
}
+ int restrictions = UX_RESTRICTIONS_UNKNOWN;
+ int restrictionMode = UX_RESTRICTION_MODE_BASELINE;
+ boolean requiresOpt = true;
while (RESTRICTIONS.equals(parser.getName())
&& parser.getEventType() == XmlResourceParser.START_TAG) {
TypedArray a = mContext.getResources().obtainAttributes(attrs,
@@ -222,23 +254,24 @@
CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
requiresOpt = a.getBoolean(
R.styleable.UxRestrictions_Restrictions_requiresDistractionOptimization, true);
+ restrictionMode = a.getInt(
+ R.styleable.UxRestrictions_Restrictions_mode, UX_RESTRICTION_MODE_BASELINE);
+
a.recycle();
parser.next();
}
- return new Pair<>(requiresOpt, restrictions);
+ return new DrivingStateRestrictions()
+ .setDistractionOptimizationRequired(requiresOpt)
+ .setRestrictions(restrictions)
+ .setMode(restrictionMode);
}
- private void addToRestrictions(int drivingState, float minSpeed, float maxSpeed,
- boolean requiresOpt, int restrictions) {
- CarUxRestrictionsConfiguration.Builder.SpeedRange speedRange = null;
- if (Float.compare(minSpeed, INVALID_SPEED) != 0) {
- if (Float.compare(maxSpeed, INVALID_SPEED) == 0) {
- // Setting min speed but not max implies MAX_SPEED.
- maxSpeed = CarUxRestrictionsConfiguration.Builder.SpeedRange.MAX_SPEED;
- }
- speedRange = new CarUxRestrictionsConfiguration.Builder.SpeedRange(minSpeed, maxSpeed);
+ @Nullable
+ private Builder.SpeedRange parseSpeedRange(float minSpeed, float maxSpeed) {
+ if (Float.compare(minSpeed, 0) < 0 || Float.compare(maxSpeed, 0) < 0) {
+ return null;
}
- mConfigBuilder.setUxRestrictions(drivingState, speedRange, requiresOpt, restrictions);
+ return new CarUxRestrictionsConfiguration.Builder.SpeedRange(minSpeed, maxSpeed);
}
private boolean traverseToTag(XmlResourceParser parser, String tag)
diff --git a/service/src/com/android/car/trust/CarTrustAgentEnrollmentService.java b/service/src/com/android/car/trust/CarTrustAgentEnrollmentService.java
index c67f33c..7c298ad 100644
--- a/service/src/com/android/car/trust/CarTrustAgentEnrollmentService.java
+++ b/service/src/com/android/car/trust/CarTrustAgentEnrollmentService.java
@@ -80,8 +80,7 @@
private BluetoothDevice mRemoteEnrollmentDevice;
@GuardedBy("this")
private boolean mEnrollmentHandshakeAccepted;
-
- private final Map<Long, Boolean> mTokenActiveState = new HashMap<>();
+ private final Map<Long, Boolean> mTokenActiveStateMap = new HashMap<>();
private String mDeviceName;
private final Context mContext;
@@ -172,6 +171,18 @@
setEnrollmentHandshakeAccepted(false);
// Disconnect from BLE
mCarTrustAgentBleManager.disconnectRemoteDevice(mRemoteEnrollmentDevice);
+ // Remove any handles that have not been activated yet.
+ Iterator<Map.Entry<Long, Boolean>> it = mTokenActiveStateMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<Long, Boolean> pair = it.next();
+ boolean isHandleActive = pair.getValue();
+ if (!isHandleActive) {
+ long handle = pair.getKey();
+ int uid = mTrustedDeviceService.getSharedPrefs().getInt(String.valueOf(handle), -1);
+ removeEscrowToken(handle, uid);
+ it.remove();
+ }
+ }
}
/**
@@ -183,8 +194,8 @@
*/
@Override
public boolean isEscrowTokenActive(long handle, int uid) {
- if (mTokenActiveState.get(handle) != null) {
- return mTokenActiveState.get(handle);
+ if (mTokenActiveStateMap.get(handle) != null) {
+ return mTokenActiveStateMap.get(handle);
}
return false;
}
@@ -193,7 +204,7 @@
* Remove the Token associated with the given handle for the given user.
*
* @param handle handle corresponding to the escrow token
- * @param uid user id
+ * @param uid user id
*/
@Override
public void removeEscrowToken(long handle, int uid) {
@@ -207,7 +218,7 @@
*/
@Override
public void removeAllTrustedDevices(int uid) {
- for (TrustedDeviceInfo device: getEnrolledDeviceInfosForUser(uid)) {
+ for (TrustedDeviceInfo device : getEnrolledDeviceInfosForUser(uid)) {
removeEscrowToken(device.getHandle(), uid);
}
}
@@ -230,12 +241,13 @@
* Enable or disable authentication of the head unit with a trusted device.
*
* @param isEnabled when set to {@code false}, head unit will not be
- * discoverable to unlock the user. Setting it to {@code true} will enable it back.
+ * discoverable to unlock the user. Setting it to {@code true} will enable it
+ * back.
*/
@Override
public void setTrustedDeviceUnlockEnabled(boolean isEnabled) {
mTrustedDeviceService.getCarTrustAgentUnlockService()
- .setTrustedDeviceUnlockEnabled(isEnabled);
+ .setTrustedDeviceUnlockEnabled(isEnabled);
}
/**
@@ -295,6 +307,9 @@
removeEscrowToken(handle, uid);
return;
}
+ // To conveniently get the user id to unlock when handle is received.
+ mTrustedDeviceService.getSharedPrefs().edit().putInt(String.valueOf(handle), uid).apply();
+ mTokenActiveStateMap.put(handle, false);
for (EnrollmentStateClient client : mEnrollmentStateClients) {
try {
client.mListener.onEscrowTokenAdded(handle);
@@ -341,12 +356,9 @@
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onEscrowTokenActiveStateChanged: " + Long.toHexString(handle));
}
- mTokenActiveState.put(handle, isTokenActive);
+ mTokenActiveStateMap.put(handle, isTokenActive);
dispatchEscrowTokenActiveStateChanged(handle, isTokenActive);
if (isTokenActive) {
- SharedPreferences.Editor editor = mTrustedDeviceService.getSharedPrefs().edit();
- // To conveniently get the user id to unlock when handle is received.
- editor.putInt(String.valueOf(handle), uid);
Set<String> deviceInfo = mTrustedDeviceService.getSharedPrefs().getStringSet(
String.valueOf(uid), new HashSet<>());
String deviceName;
@@ -360,13 +372,11 @@
deviceInfo.add(new TrustedDeviceInfo(handle, mRemoteEnrollmentDevice.getAddress(),
deviceName).serialize());
// To conveniently get the devices info regarding certain user.
- editor.putStringSet(String.valueOf(uid), deviceInfo);
- editor.apply();
-
+ mTrustedDeviceService.getSharedPrefs().edit().putStringSet(String.valueOf(uid),
+ deviceInfo).apply();
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Sending handle: " + handle);
}
-
mCarTrustAgentBleManager.sendEnrollmentHandle(mRemoteEnrollmentDevice,
mEncryptionKey.encryptData(Utils.longToBytes(handle)));
} else {
@@ -466,7 +476,7 @@
* <p>This method should be called continually until {@link #mEnrollmentHandshakeAccepted} is
* {@code true}, meaning an secure channel has been set up.
*
- * @param message The message received from the connected device.
+ * @param message The message received from the connected device.
* @throws HandshakeException If an error was encountered during the handshake flow.
*/
private void processInitEncryptionMessage(byte[] message) throws HandshakeException {
diff --git a/tests/DirectRenderingClusterSample/Android.mk b/tests/DirectRenderingClusterSample/Android.mk
index 41d2a65..28a5a78 100644
--- a/tests/DirectRenderingClusterSample/Android.mk
+++ b/tests/DirectRenderingClusterSample/Android.mk
@@ -40,7 +40,8 @@
androidx.car_car-cluster \
car-arch-common \
car-media-common \
- car-telephony-common
+ car-telephony-common \
+ car-apps-common
include $(BUILD_PACKAGE)
diff --git a/tests/DirectRenderingClusterSample/res/layout/fragment_music.xml b/tests/DirectRenderingClusterSample/res/layout/fragment_music.xml
index 3071c72..f9c72f7 100644
--- a/tests/DirectRenderingClusterSample/res/layout/fragment_music.xml
+++ b/tests/DirectRenderingClusterSample/res/layout/fragment_music.xml
@@ -23,7 +23,7 @@
app:cardElevation="0dp"
app:cardCornerRadius="6dp">
- <com.android.car.media.common.CrossfadeImageView
+ <com.android.car.apps.common.CrossfadeImageView
android:id="@+id/album_background"
android:foreground="?android:attr/selectableItemBackground"
android:layout_width="match_parent"
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarUxRestrictionsConfigurationTest.java b/tests/android_car_api_test/src/android/car/apitest/CarUxRestrictionsConfigurationTest.java
index 5b991a9..155970d 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarUxRestrictionsConfigurationTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarUxRestrictionsConfigurationTest.java
@@ -247,7 +247,15 @@
new Builder.SpeedRange(0f, MAX_SPEED);
}
- public void testSpeedRange_NegativeMax() {
+ public void testSpeedRange_NoNegativeMin() {
+ try {
+ new Builder.SpeedRange(-2f, 1f);
+ } catch (Exception e) {
+ // Expected exception.
+ }
+ }
+
+ public void testSpeedRange_NoNegativeMax() {
try {
new Builder.SpeedRange(2f, -1f);
} catch (Exception e) {
@@ -255,6 +263,14 @@
}
}
+ public void testSpeedRange_MinCannotBeMaxSpeed() {
+ try {
+ new Builder.SpeedRange(MAX_SPEED, 1f);
+ } catch (Exception e) {
+ // Expected exception.
+ }
+ }
+
public void testSpeedRange_MinGreaterThanMax() {
try {
new Builder.SpeedRange(5f, 2f);
diff --git a/tests/carservice_test/res/xml/ux_restrictions_passenger_mode.xml b/tests/carservice_test/res/xml/ux_restrictions_passenger_mode.xml
new file mode 100644
index 0000000..6a5dd07
--- /dev/null
+++ b/tests/carservice_test/res/xml/ux_restrictions_passenger_mode.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+This xml contains UX restrictions configuration for testing.
+-->
+<UxRestrictions xmlns:car="http://schemas.android.com/apk/res-auto">
+ <RestrictionMapping>
+ <DrivingState car:state="parked">
+ <Restrictions car:mode="passenger"
+ car:requiresDistractionOptimization="false" car:uxr="baseline"/>
+ <Restrictions
+ car:requiresDistractionOptimization="true" car:uxr="no_video"/>
+ </DrivingState>
+ <DrivingState car:state="idling">
+ <Restrictions car:mode="passenger"
+ car:requiresDistractionOptimization="false" car:uxr="baseline"/>
+ <Restrictions
+ car:requiresDistractionOptimization="true" car:uxr="no_video"/>
+ </DrivingState>
+ <!-- Verify parsing multiple DrivingState tags also works.-->
+ <DrivingState car:state="moving">
+ <Restrictions car:mode="passenger"
+ car:requiresDistractionOptimization="false" car:uxr="baseline"/>
+ </DrivingState>
+ <DrivingState car:state="moving">
+ <Restrictions
+ car:requiresDistractionOptimization="true" car:uxr="no_video"/>
+ </DrivingState>
+ </RestrictionMapping>
+</UxRestrictions>
diff --git a/tests/carservice_test/src/com/android/car/CarUxRestrictionsConfigurationXmlParserTest.java b/tests/carservice_test/src/com/android/car/CarUxRestrictionsConfigurationXmlParserTest.java
index cad210e..3a0dc4a 100644
--- a/tests/carservice_test/src/com/android/car/CarUxRestrictionsConfigurationXmlParserTest.java
+++ b/tests/carservice_test/src/com/android/car/CarUxRestrictionsConfigurationXmlParserTest.java
@@ -18,6 +18,8 @@
import static android.car.drivingstate.CarDrivingStateEvent.DRIVING_STATE_IDLING;
import static android.car.drivingstate.CarDrivingStateEvent.DRIVING_STATE_MOVING;
import static android.car.drivingstate.CarDrivingStateEvent.DRIVING_STATE_PARKED;
+import static android.car.drivingstate.CarUxRestrictionsManager.UX_RESTRICTION_MODE_BASELINE;
+import static android.car.drivingstate.CarUxRestrictionsManager.UX_RESTRICTION_MODE_PASSENGER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -108,4 +110,44 @@
assertTrue(fast.isRequiresDistractionOptimization());
assertEquals(CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO, fast.getActiveRestrictions());
}
+
+ @Test
+ public void testParsingPassengerState() throws IOException, XmlPullParserException {
+ CarUxRestrictionsConfiguration config = CarUxRestrictionsConfigurationXmlParser.parse(
+ getContext(), R.xml.ux_restrictions_passenger_mode);
+
+ CarUxRestrictions moving = config.getUxRestrictions(
+ DRIVING_STATE_MOVING, 1f, UX_RESTRICTION_MODE_PASSENGER);
+ assertFalse(moving.isRequiresDistractionOptimization());
+
+ CarUxRestrictions idling = config.getUxRestrictions(
+ DRIVING_STATE_IDLING, 0f, UX_RESTRICTION_MODE_PASSENGER);
+ assertFalse(idling.isRequiresDistractionOptimization());
+
+ CarUxRestrictions parked = config.getUxRestrictions(
+ DRIVING_STATE_PARKED, 0f, UX_RESTRICTION_MODE_PASSENGER);
+ assertFalse(parked.isRequiresDistractionOptimization());
+ }
+
+ @Test
+ public void testParsingPassengerMode_ValuesInBaselineAreNotAffected()
+ throws IOException, XmlPullParserException {
+ CarUxRestrictionsConfiguration config = CarUxRestrictionsConfigurationXmlParser.parse(
+ getContext(), R.xml.ux_restrictions_passenger_mode);
+
+ CarUxRestrictions moving = config.getUxRestrictions(
+ DRIVING_STATE_MOVING, 1f, UX_RESTRICTION_MODE_BASELINE);
+ assertTrue(moving.isRequiresDistractionOptimization());
+ assertEquals(CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO, moving.getActiveRestrictions());
+
+ CarUxRestrictions idling = config.getUxRestrictions(
+ DRIVING_STATE_IDLING, 0f, UX_RESTRICTION_MODE_BASELINE);
+ assertTrue(idling.isRequiresDistractionOptimization());
+ assertEquals(CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO, idling.getActiveRestrictions());
+
+ CarUxRestrictions parked = config.getUxRestrictions(
+ DRIVING_STATE_PARKED, 0f, UX_RESTRICTION_MODE_BASELINE);
+ assertTrue(parked.isRequiresDistractionOptimization());
+ assertEquals(CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO, parked.getActiveRestrictions());
+ }
}