1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car; 18 19 import static android.car.builtin.view.DisplayHelper.INVALID_PORT; 20 import static android.car.drivingstate.CarUxRestrictionsConfiguration.Builder.SpeedRange.MAX_SPEED; 21 import static android.car.drivingstate.CarUxRestrictionsManager.UX_RESTRICTION_MODE_BASELINE; 22 23 import android.annotation.Nullable; 24 import android.annotation.XmlRes; 25 import android.car.CarOccupantZoneManager; 26 import android.car.builtin.util.Slogf; 27 import android.car.drivingstate.CarDrivingStateEvent; 28 import android.car.drivingstate.CarUxRestrictions; 29 import android.car.drivingstate.CarUxRestrictionsConfiguration; 30 import android.car.drivingstate.CarUxRestrictionsConfiguration.DrivingStateRestrictions; 31 import android.content.Context; 32 import android.content.res.XmlResourceParser; 33 import android.util.Log; 34 35 import org.xmlpull.v1.XmlPullParserException; 36 37 import java.io.IOException; 38 import java.util.ArrayList; 39 import java.util.List; 40 import java.util.Locale; 41 42 /** 43 * @hide 44 */ 45 public final class CarUxRestrictionsConfigurationXmlParser { 46 private static final String TAG = CarLog.tagFor(CarUxRestrictionsConfigurationXmlParser.class); 47 private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG); 48 private static final int UX_RESTRICTIONS_UNKNOWN = -1; 49 private static final float INVALID_SPEED = -1f; 50 private static final String XML_NAMESPACE = null; 51 52 // XML tags 53 private static final String XML_ROOT_ELEMENT = "UxRestrictions"; 54 private static final String XML_RESTRICTION_MAPPING = "RestrictionMapping"; 55 private static final String XML_RESTRICTION_PARAMETERS = "RestrictionParameters"; 56 private static final String XML_DRIVING_STATE = "DrivingState"; 57 private static final String XML_RESTRICTIONS = "Restrictions"; 58 private static final String XML_STRING_RESTRICTIONS = "StringRestrictions"; 59 private static final String XML_CONTENT_RESTRICTIONS = "ContentRestrictions"; 60 61 // XML attributes 62 private static final String XML_PHYSICAL_PORT = "physicalPort"; 63 private static final String XML_OCCUPANT_ZONE_ID = "occupantZoneId"; 64 private static final String XML_DISPLAY_TYPE = "displayType"; 65 66 private static final String XML_STATE = "state"; 67 private static final String XML_MIN_SPEED = "minSpeed"; 68 private static final String XML_MAX_SPEED = "maxSpeed"; 69 private static final String XML_MODE = "mode"; 70 private static final String XML_UXR = "uxr"; 71 private static final String XML_REQUIRES_DISTRACTION_OPTIMIZATION = 72 "requiresDistractionOptimization"; 73 private static final String XML_MAX_LENGTH = "maxLength"; 74 private static final String XML_MAX_CUMULATIVE_ITEMS = "maxCumulativeItems"; 75 private static final String XML_MAX_DEPTH = "maxDepth"; 76 77 // XML attribute values 78 private static final String XML_STATE_PARKED = "parked"; 79 private static final String XML_STATE_IDLING = "idling"; 80 private static final String XML_STATE_MOVING = "moving"; 81 private static final String XML_UXR_BASELINE = "baseline"; 82 private static final String XML_UXR_NO_DIALPAD = "no_dialpad"; 83 private static final String XML_UXR_NO_FILTERING = "no_filtering"; 84 private static final String XML_UXR_LIMIT_STRING_LENGTH = "limit_string_length"; 85 private static final String XML_UXR_NO_KEYBOARD = "no_keyboard"; 86 private static final String XML_UXR_NO_VIDEO = "no_video"; 87 private static final String XML_UXR_LIMIT_CONTENT = "limit_content"; 88 private static final String XML_UXR_NO_SETUP = "no_setup"; 89 private static final String XML_UXR_NO_TEXT_MESSAGE = "no_text_message"; 90 private static final String XML_UXR_NO_VOICE_TRANSCRIPTION = "no_voice_transcription"; 91 private static final String XML_UXR_FULLY_RESTRICTED = "fully_restricted"; 92 93 private final Context mContext; 94 95 private int mGlobalMaxRestrictedStringLength = UX_RESTRICTIONS_UNKNOWN; 96 private int mGlobalMaxCumulativeContentItems = UX_RESTRICTIONS_UNKNOWN; 97 private int mGlobalMaxContentDepth = UX_RESTRICTIONS_UNKNOWN; 98 private final List<CarUxRestrictionsConfiguration.Builder> mConfigBuilders = new ArrayList<>(); 99 CarUxRestrictionsConfigurationXmlParser(Context context)100 private CarUxRestrictionsConfigurationXmlParser(Context context) { 101 mContext = context; 102 } 103 104 /** 105 * Loads the UX restrictions related information from the XML resource. 106 * 107 * @return parsed CarUxRestrictionsConfiguration; {@code null} if the XML is malformed. 108 */ 109 @Nullable parse( Context context, @XmlRes int xmlResource)110 public static List<CarUxRestrictionsConfiguration> parse( 111 Context context, @XmlRes int xmlResource) 112 throws IOException, XmlPullParserException { 113 return new CarUxRestrictionsConfigurationXmlParser(context).parse(xmlResource); 114 } 115 116 @Nullable parse(@mlRes int xmlResource)117 private List<CarUxRestrictionsConfiguration> parse(@XmlRes int xmlResource) 118 throws IOException, XmlPullParserException { 119 120 XmlResourceParser parser = mContext.getResources().getXml(xmlResource); 121 if (parser == null) { 122 Slogf.e(TAG, "Invalid Xml resource"); 123 return null; 124 } 125 126 if (!traverseUntilStartTag(parser)) { 127 Slogf.e(TAG, "XML root element invalid: " + parser.getName()); 128 return null; 129 } 130 131 if (!traverseUntilEndOfDocument(parser)) { 132 Slogf.e(TAG, "Could not parse XML to end"); 133 return null; 134 } 135 136 List<CarUxRestrictionsConfiguration> configs = new ArrayList<>(); 137 for (int i = 0, length = mConfigBuilders.size(); i < length; i++) { 138 CarUxRestrictionsConfiguration.Builder builder = mConfigBuilders.get(i); 139 builder.setMaxStringLengthIfNotSet(mGlobalMaxRestrictedStringLength) 140 .setMaxCumulativeContentItemsIfNotSet(mGlobalMaxCumulativeContentItems) 141 .setMaxContentDepthIfNotSet(mGlobalMaxContentDepth); 142 configs.add(builder.build()); 143 } 144 return configs; 145 } 146 traverseUntilStartTag(XmlResourceParser parser)147 private boolean traverseUntilStartTag(XmlResourceParser parser) 148 throws IOException, XmlPullParserException { 149 int type; 150 // Traverse till the first tag is hit 151 while ((type = parser.next()) != XmlResourceParser.END_DOCUMENT 152 && type != XmlResourceParser.START_TAG) { 153 // Do nothing. 154 } 155 return XML_ROOT_ELEMENT.equals(parser.getName()); 156 } 157 traverseUntilEndOfDocument(XmlResourceParser parser)158 private boolean traverseUntilEndOfDocument(XmlResourceParser parser) 159 throws XmlPullParserException, IOException { 160 while (parser.getEventType() != XmlResourceParser.END_DOCUMENT) { 161 // Every time a start tag is hit, check for the type of the tag 162 // and load the corresponding information. 163 if (parser.next() == XmlResourceParser.START_TAG) { 164 switch (parser.getName()) { 165 case XML_RESTRICTION_MAPPING: 166 // Each RestrictionMapping tag represents a new set of rules. 167 CarUxRestrictionsConfiguration.Builder builder = 168 new CarUxRestrictionsConfiguration.Builder(); 169 mConfigBuilders.add(builder); 170 171 if (!mapDrivingStateToRestrictions(parser)) { 172 Slogf.e(TAG, "Could not map driving state to restriction."); 173 return false; 174 } 175 parseLocalRestrictionParameters(parser, builder); 176 break; 177 case XML_RESTRICTION_PARAMETERS: 178 if (!parseGlobalRestrictionParameters(parser)) { 179 // Failure to parse is automatically handled by falling back to 180 // defaults. Just log the information here. 181 Slogf.w(TAG, "Error reading restrictions parameters. " 182 + "Falling back to platform defaults."); 183 } 184 break; 185 default: 186 Slogf.w(TAG, "Unknown class:" + parser.getName()); 187 } 188 } 189 } 190 return true; 191 } 192 193 /** 194 * Parses the information in the local {@code RestrictionParameters} within a 195 * {@code RestrictionMapping} container tag to read the parameters for the applicable UX 196 * restrictions. 197 */ parseLocalRestrictionParameters(XmlResourceParser parser, CarUxRestrictionsConfiguration.Builder builder)198 private void parseLocalRestrictionParameters(XmlResourceParser parser, 199 CarUxRestrictionsConfiguration.Builder builder) 200 throws IOException, XmlPullParserException { 201 if (parser == null) { 202 Slogf.e(TAG, "Parser is null"); 203 return; 204 } 205 206 if (XML_RESTRICTION_MAPPING.equals(parser.getName())) { 207 if (DBG) { 208 Slogf.d(TAG, 209 "No local restriction parameters for this, the global restriction " 210 + "parameters will be used"); 211 } 212 return; 213 } 214 if (!XML_RESTRICTION_PARAMETERS.equals(parser.getName())) { 215 if (DBG) { 216 Slogf.d(TAG, 217 "Unsupported Restriction Parameters in XML: %s, the global restriction " 218 + "parameters will be used", parser.getName()); 219 } 220 return; 221 } 222 parseRestrictionParameters(parser, builder); 223 } 224 parseRestrictionParameters(XmlResourceParser parser, @Nullable CarUxRestrictionsConfiguration.Builder builder)225 private void parseRestrictionParameters(XmlResourceParser parser, 226 @Nullable CarUxRestrictionsConfiguration.Builder builder) 227 throws IOException, XmlPullParserException { 228 while (parser.getEventType() != XmlResourceParser.END_DOCUMENT) { 229 int type = parser.next(); 230 // Break if all <RestrictionParameters> are parsed 231 if (type == XmlResourceParser.END_TAG && XML_RESTRICTION_PARAMETERS.equals( 232 parser.getName())) { 233 return; 234 } 235 236 if (type == XmlResourceParser.START_TAG) { 237 switch (parser.getName()) { 238 case XML_STRING_RESTRICTIONS: 239 setStringRestrictionParameters(builder, parser); 240 break; 241 case XML_CONTENT_RESTRICTIONS: 242 setContentRestrictionParameters(builder, parser); 243 break; 244 default: 245 Slogf.i(TAG, "Unsupported Restriction Parameters in XML: %s", 246 parser.getName()); 247 break; 248 } 249 } 250 } 251 } 252 253 /** 254 * Adds string restriction parameters to the {@link CarUxRestrictionsConfiguration.Builder} 255 * object. 256 */ setStringRestrictionParameters(CarUxRestrictionsConfiguration.Builder builder, XmlResourceParser parser)257 private void setStringRestrictionParameters(CarUxRestrictionsConfiguration.Builder builder, 258 XmlResourceParser parser) { 259 int maxRestrictedStringLength = parser.getAttributeIntValue(XML_NAMESPACE, XML_MAX_LENGTH, 260 UX_RESTRICTIONS_UNKNOWN); 261 if (builder != null) { 262 builder.setMaxStringLengthIfNotSet(maxRestrictedStringLength); 263 } else { 264 mGlobalMaxRestrictedStringLength = maxRestrictedStringLength; 265 } 266 } 267 268 /** 269 * Adds content restriction parameters to the {@link CarUxRestrictionsConfiguration.Builder} 270 * object. 271 */ setContentRestrictionParameters(CarUxRestrictionsConfiguration.Builder builder, XmlResourceParser parser)272 private void setContentRestrictionParameters(CarUxRestrictionsConfiguration.Builder builder, 273 XmlResourceParser parser) { 274 int maxCumulativeContentItems = parser.getAttributeIntValue(XML_NAMESPACE, 275 XML_MAX_CUMULATIVE_ITEMS, UX_RESTRICTIONS_UNKNOWN); 276 int maxContentDepth = parser.getAttributeIntValue(XML_NAMESPACE, XML_MAX_DEPTH, 277 UX_RESTRICTIONS_UNKNOWN); 278 if (builder != null) { 279 // Set local restriction parameters 280 builder.setMaxContentDepthIfNotSet(maxContentDepth); 281 builder.setMaxCumulativeContentItemsIfNotSet(maxCumulativeContentItems); 282 } else { 283 // Set global restriction parameters 284 mGlobalMaxCumulativeContentItems = maxCumulativeContentItems; 285 mGlobalMaxContentDepth = maxContentDepth; 286 } 287 } 288 289 /** 290 * Parses the information in the <restrictionMapping> tag to construct the mapping from 291 * driving state to UX restrictions. 292 */ mapDrivingStateToRestrictions(XmlResourceParser parser)293 private boolean mapDrivingStateToRestrictions(XmlResourceParser parser) 294 throws IOException, XmlPullParserException { 295 if (parser == null) { 296 Slogf.e(TAG, "Invalid arguments"); 297 return false; 298 } 299 // The parser should be at the <RestrictionMapping> tag at this point. 300 if (!XML_RESTRICTION_MAPPING.equals(parser.getName())) { 301 Slogf.e(TAG, "Parser not at RestrictionMapping element: " + parser.getName()); 302 return false; 303 } 304 // read port 305 int portValue = parser.getAttributeIntValue(XML_NAMESPACE, XML_PHYSICAL_PORT, 306 INVALID_PORT); 307 if (portValue != INVALID_PORT) { 308 int port = CarUxRestrictionsConfiguration.Builder.validatePort(portValue); 309 getCurrentBuilder().setPhysicalPort(port); 310 } 311 312 // read occupant zone id 313 int zoneIdValue = parser.getAttributeIntValue(XML_NAMESPACE, XML_OCCUPANT_ZONE_ID, 314 CarOccupantZoneManager.OccupantZoneInfo.INVALID_ZONE_ID); 315 if (zoneIdValue != CarOccupantZoneManager.OccupantZoneInfo.INVALID_ZONE_ID) { 316 int zoneId = CarUxRestrictionsConfiguration.Builder.validateOccupantZoneId(zoneIdValue); 317 getCurrentBuilder().setOccupantZoneId(zoneId); 318 } 319 320 // read occupant zone id 321 int displayTypeValue = parser.getAttributeIntValue(XML_NAMESPACE, XML_DISPLAY_TYPE, 322 CarOccupantZoneManager.DISPLAY_TYPE_UNKNOWN); 323 if (displayTypeValue != CarOccupantZoneManager.DISPLAY_TYPE_UNKNOWN) { 324 int displayType = CarUxRestrictionsConfiguration.Builder.validateDisplayType( 325 displayTypeValue); 326 getCurrentBuilder().setDisplayType(displayType); 327 } 328 329 if (!traverseToTag(parser, XML_DRIVING_STATE)) { 330 Slogf.e(TAG, "No <" + XML_DRIVING_STATE + "> tag in XML"); 331 return false; 332 } 333 // Handle all the <DrivingState> tags. 334 while (XML_DRIVING_STATE.equals(parser.getName())) { 335 if (parser.getEventType() == XmlResourceParser.START_TAG) { 336 // 1. Get the driving state attributes: driving state and speed range 337 int drivingState = getDrivingState( 338 parser.getAttributeValue(XML_NAMESPACE, XML_STATE)); 339 float minSpeed = 0; 340 try { 341 minSpeed = Float 342 .parseFloat(parser.getAttributeValue(XML_NAMESPACE, XML_MIN_SPEED)); 343 } catch (NullPointerException | NumberFormatException e) { 344 minSpeed = INVALID_SPEED; 345 } 346 347 float maxSpeed = 0; 348 try { 349 maxSpeed = Float 350 .parseFloat(parser.getAttributeValue(XML_NAMESPACE, XML_MAX_SPEED)); 351 } catch (NullPointerException | NumberFormatException e) { 352 maxSpeed = MAX_SPEED; 353 } 354 355 // 2. Traverse to the <Restrictions> tag 356 if (!traverseToTag(parser, XML_RESTRICTIONS)) { 357 Slogf.e(TAG, "No <" + XML_RESTRICTIONS + "> tag in XML"); 358 return false; 359 } 360 361 // 3. Parse the restrictions for this driving state 362 CarUxRestrictionsConfiguration.Builder.SpeedRange speedRange = parseSpeedRange( 363 minSpeed, maxSpeed); 364 if (!parseAllRestrictions(parser, drivingState, speedRange)) { 365 Slogf.e(TAG, "Could not parse restrictions for driving state:" + drivingState); 366 return false; 367 } 368 } 369 parser.next(); 370 } 371 return true; 372 } 373 getDrivingState(String state)374 private int getDrivingState(String state) { 375 if (state == null) { 376 return CarDrivingStateEvent.DRIVING_STATE_UNKNOWN; 377 } 378 379 switch (state.trim().toLowerCase(Locale.ROOT)) { 380 case XML_STATE_PARKED: 381 return CarDrivingStateEvent.DRIVING_STATE_PARKED; 382 case XML_STATE_IDLING: 383 return CarDrivingStateEvent.DRIVING_STATE_IDLING; 384 case XML_STATE_MOVING: 385 return CarDrivingStateEvent.DRIVING_STATE_MOVING; 386 default: 387 return CarDrivingStateEvent.DRIVING_STATE_UNKNOWN; 388 } 389 } 390 391 /** 392 * Parses all <restrictions> tags nested with <drivingState> tag. 393 */ parseAllRestrictions(XmlResourceParser parser, int drivingState, CarUxRestrictionsConfiguration.Builder.SpeedRange speedRange)394 private boolean parseAllRestrictions(XmlResourceParser parser, 395 int drivingState, CarUxRestrictionsConfiguration.Builder.SpeedRange speedRange) 396 throws IOException, XmlPullParserException { 397 if (parser == null) { 398 Slogf.e(TAG, "Invalid arguments"); 399 return false; 400 } 401 // The parser should be at the <Restrictions> tag at this point. 402 if (!XML_RESTRICTIONS.equals(parser.getName())) { 403 Slogf.e(TAG, "Parser not at Restrictions element: " + parser.getName()); 404 return false; 405 } 406 while (XML_RESTRICTIONS.equals(parser.getName())) { 407 if (parser.getEventType() == XmlResourceParser.START_TAG) { 408 // Parse one restrictions tag. 409 List<DrivingStateRestrictions> restrictions = parseRestrictions(parser); 410 if (restrictions == null || restrictions.isEmpty()) { 411 Slogf.e(TAG, ""); 412 return false; 413 } 414 // Update the builder if the driving state and restrictions info are valid. 415 if (drivingState != CarDrivingStateEvent.DRIVING_STATE_UNKNOWN 416 && restrictions != null) { 417 for (int i = 0; i < restrictions.size(); i++) { 418 DrivingStateRestrictions restriction = restrictions.get(i); 419 restriction.setSpeedRange(speedRange); 420 421 if (DBG) { 422 Slogf.d(TAG, "Map " + drivingState + " : " + restriction); 423 } 424 getCurrentBuilder().setUxRestrictions(drivingState, restriction); 425 } 426 } 427 } 428 parser.next(); 429 } 430 return true; 431 } 432 433 /** 434 * Parses the <restrictions> tag nested with the <drivingState>. This provides the restrictions 435 * for the enclosing driving state. 436 * 437 * @return Driving state restrictions list. The list would contain more than one value if mode 438 * attribute defines more than one mode separated by "|". 439 */ 440 @Nullable parseRestrictions(XmlResourceParser parser)441 private List<DrivingStateRestrictions> parseRestrictions(XmlResourceParser parser) 442 throws IOException, XmlPullParserException { 443 if (parser == null) { 444 Slogf.e(TAG, "Invalid Arguments"); 445 return null; 446 } 447 448 int restrictions = UX_RESTRICTIONS_UNKNOWN; 449 List<String> restrictionModes = new ArrayList<>(); 450 boolean requiresOpt = true; 451 if (XML_RESTRICTIONS.equals(parser.getName()) 452 && parser.getEventType() == XmlResourceParser.START_TAG) { 453 restrictions = getRestrictions(parser.getAttributeValue(XML_NAMESPACE, XML_UXR)); 454 updateModes(parser.getAttributeValue(XML_NAMESPACE, XML_MODE), restrictionModes); 455 requiresOpt = parser.getAttributeBooleanValue(XML_NAMESPACE, 456 XML_REQUIRES_DISTRACTION_OPTIMIZATION, true); 457 parser.next(); 458 } 459 460 List<DrivingStateRestrictions> drivingStateRestrictions = new ArrayList<>(); 461 462 for (int i = 0; i < restrictionModes.size(); i++) { 463 drivingStateRestrictions.add(new DrivingStateRestrictions() 464 .setDistractionOptimizationRequired(requiresOpt) 465 .setRestrictions(restrictions) 466 .setMode(restrictionModes.get(i))); 467 } 468 469 return drivingStateRestrictions; 470 } 471 updateModes(String allModes, List<String> modes)472 private void updateModes(String allModes, List<String> modes) { 473 if (allModes == null) { 474 modes.add(UX_RESTRICTION_MODE_BASELINE); 475 return; 476 } 477 String[] allModesArray = allModes.split("\\|"); 478 479 for (int i = 0; i < allModesArray.length; i++) { 480 modes.add(allModesArray[i].trim()); 481 } 482 } 483 getRestrictions(String allRestrictions)484 private int getRestrictions(String allRestrictions) { 485 if (allRestrictions == null) { 486 return CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED; 487 } 488 int restrictionsValue = 0; 489 String[] restrictions = allRestrictions.split("\\|"); 490 for (int i = 0; i < restrictions.length; i++) { 491 String restriction = restrictions[i].trim().toLowerCase(Locale.ROOT); 492 switch (restriction) { 493 case XML_UXR_BASELINE: 494 restrictionsValue = restrictionsValue 495 | CarUxRestrictions.UX_RESTRICTIONS_BASELINE; 496 break; 497 case XML_UXR_NO_DIALPAD: 498 restrictionsValue = restrictionsValue 499 | CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD; 500 break; 501 case XML_UXR_NO_FILTERING: 502 restrictionsValue = restrictionsValue 503 | CarUxRestrictions.UX_RESTRICTIONS_NO_FILTERING; 504 break; 505 case XML_UXR_LIMIT_STRING_LENGTH: 506 restrictionsValue = restrictionsValue 507 | CarUxRestrictions.UX_RESTRICTIONS_LIMIT_STRING_LENGTH; 508 break; 509 case XML_UXR_NO_KEYBOARD: 510 restrictionsValue = restrictionsValue 511 | CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD; 512 break; 513 case XML_UXR_NO_VIDEO: 514 restrictionsValue = restrictionsValue 515 | CarUxRestrictions.UX_RESTRICTIONS_NO_VIDEO; 516 break; 517 case XML_UXR_LIMIT_CONTENT: 518 restrictionsValue = restrictionsValue 519 | CarUxRestrictions.UX_RESTRICTIONS_LIMIT_CONTENT; 520 break; 521 case XML_UXR_NO_SETUP: 522 restrictionsValue = restrictionsValue 523 | CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP; 524 break; 525 case XML_UXR_NO_TEXT_MESSAGE: 526 restrictionsValue = restrictionsValue 527 | CarUxRestrictions.UX_RESTRICTIONS_NO_TEXT_MESSAGE; 528 break; 529 case XML_UXR_NO_VOICE_TRANSCRIPTION: 530 restrictionsValue = restrictionsValue 531 | CarUxRestrictions.UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION; 532 break; 533 case XML_UXR_FULLY_RESTRICTED: 534 restrictionsValue = restrictionsValue 535 | CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED; 536 break; 537 default: 538 break; 539 } 540 } 541 return restrictionsValue; 542 } 543 544 @Nullable parseSpeedRange(float minSpeed, float maxSpeed)545 private CarUxRestrictionsConfiguration.Builder.SpeedRange parseSpeedRange(float minSpeed, 546 float maxSpeed) { 547 if (Float.compare(minSpeed, 0) < 0 || Float.compare(maxSpeed, 0) < 0) { 548 return null; 549 } 550 return new CarUxRestrictionsConfiguration.Builder.SpeedRange(minSpeed, maxSpeed); 551 } 552 traverseToTag(XmlResourceParser parser, String tag)553 private boolean traverseToTag(XmlResourceParser parser, String tag) 554 throws IOException, XmlPullParserException { 555 if (tag == null || parser == null) { 556 return false; 557 } 558 int type; 559 while ((type = parser.next()) != XmlResourceParser.END_DOCUMENT) { 560 if (type == XmlResourceParser.START_TAG && parser.getName().equals(tag)) { 561 return true; 562 } 563 } 564 return false; 565 } 566 567 /** 568 * Parses the information in the global {@code RestrictionParameters} in a 569 * {@code UxRestrictions} tag to read the parameters for the applicable UX restrictions. 570 */ parseGlobalRestrictionParameters(XmlResourceParser parser)571 private boolean parseGlobalRestrictionParameters(XmlResourceParser parser) 572 throws IOException, XmlPullParserException { 573 if (parser == null) { 574 Slogf.e(TAG, "Parser is null"); 575 return false; 576 } 577 // The parser should be at the <RestrictionParameters> tag at this point. 578 if (!XML_RESTRICTION_PARAMETERS.equals(parser.getName())) { 579 Slogf.e(TAG, "Parser not at RestrictionParameters element: %s", parser.getName()); 580 return false; 581 } 582 parseRestrictionParameters(parser, null); 583 return true; 584 } 585 getCurrentBuilder()586 private CarUxRestrictionsConfiguration.Builder getCurrentBuilder() { 587 return mConfigBuilders.get(mConfigBuilders.size() - 1); 588 } 589 } 590