1 /* 2 * Copyright (C) 2015 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 android.car; 18 19 import android.annotation.IntDef; 20 import android.annotation.Nullable; 21 import android.annotation.SystemApi; 22 import android.car.cluster.CarInstrumentClusterManager; 23 import android.car.content.pm.CarPackageManager; 24 import android.car.diagnostic.CarDiagnosticManager; 25 import android.car.drivingstate.CarDrivingStateManager; 26 import android.car.drivingstate.CarUxRestrictionsManager; 27 import android.car.hardware.CarSensorManager; 28 import android.car.hardware.CarVendorExtensionManager; 29 import android.car.hardware.cabin.CarCabinManager; 30 import android.car.hardware.hvac.CarHvacManager; 31 import android.car.hardware.power.CarPowerManager; 32 import android.car.hardware.property.CarPropertyManager; 33 import android.car.media.CarAudioManager; 34 import android.car.navigation.CarNavigationStatusManager; 35 import android.car.settings.CarConfigurationManager; 36 import android.car.storagemonitoring.CarStorageMonitoringManager; 37 import android.car.test.CarTestManagerBinderWrapper; 38 import android.car.vms.VmsSubscriberManager; 39 import android.content.ComponentName; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.content.ServiceConnection; 43 import android.content.pm.PackageManager; 44 import android.os.Handler; 45 import android.os.IBinder; 46 import android.os.Looper; 47 import android.os.RemoteException; 48 import android.os.UserHandle; 49 import android.util.Log; 50 51 import com.android.internal.annotations.GuardedBy; 52 53 import java.lang.annotation.Retention; 54 import java.lang.annotation.RetentionPolicy; 55 import java.util.HashMap; 56 57 /** 58 * Top level car API for embedded Android Auto deployments. 59 * This API works only for devices with {@link PackageManager#FEATURE_AUTOMOTIVE} 60 * Calling this API on a device with no such feature will lead to an exception. 61 */ 62 public final class Car { 63 64 /** 65 * Represent the version of Car API. This is only updated when there is API change. 66 * 1 : N 67 * 2 : O 68 * 3 : O-MR1 69 */ 70 public static final int VERSION = 3; 71 72 /** Service name for {@link CarSensorManager}, to be used in {@link #getCarManager(String)}. */ 73 public static final String SENSOR_SERVICE = "sensor"; 74 75 /** Service name for {@link CarInfoManager}, to be used in {@link #getCarManager(String)}. */ 76 public static final String INFO_SERVICE = "info"; 77 78 /** Service name for {@link CarAppFocusManager}. */ 79 public static final String APP_FOCUS_SERVICE = "app_focus"; 80 81 /** Service name for {@link CarPackageManager} */ 82 public static final String PACKAGE_SERVICE = "package"; 83 84 /** Service name for {@link CarAudioManager} */ 85 public static final String AUDIO_SERVICE = "audio"; 86 87 /** Service name for {@link CarNavigationStatusManager} */ 88 public static final String CAR_NAVIGATION_SERVICE = "car_navigation_service"; 89 90 /** 91 * Service name for {@link CarInstrumentClusterManager} 92 * @hide 93 */ 94 public static final String CAR_INSTRUMENT_CLUSTER_SERVICE = "cluster_service"; 95 96 /** 97 * @hide 98 */ 99 @SystemApi 100 public static final String CABIN_SERVICE = "cabin"; 101 102 /** 103 * @hide 104 */ 105 @SystemApi 106 public static final String DIAGNOSTIC_SERVICE = "diagnostic"; 107 108 /** 109 * @hide 110 */ 111 @SystemApi 112 public static final String HVAC_SERVICE = "hvac"; 113 114 /** 115 * @hide 116 */ 117 @SystemApi 118 public static final String POWER_SERVICE = "power"; 119 120 /** 121 * @hide 122 */ 123 @SystemApi 124 public static final String PROJECTION_SERVICE = "projection"; 125 126 /** 127 * @hide 128 */ 129 @SystemApi 130 public static final String PROPERTY_SERVICE = "property"; 131 132 /** 133 * @hide 134 */ 135 @SystemApi 136 public static final String VENDOR_EXTENSION_SERVICE = "vendor_extension"; 137 138 /** 139 * @hide 140 */ 141 public static final String BLUETOOTH_SERVICE = "car_bluetooth"; 142 143 /** 144 * @hide 145 */ 146 @SystemApi 147 public static final String VMS_SUBSCRIBER_SERVICE = "vehicle_map_subscriber_service"; 148 149 /** 150 * Service name for {@link CarDrivingStateManager} 151 * @hide 152 */ 153 @SystemApi 154 public static final String CAR_DRIVING_STATE_SERVICE = "drivingstate"; 155 156 /** 157 * Service name for {@link CarUxRestrictionsManager} 158 */ 159 public static final String CAR_UX_RESTRICTION_SERVICE = "uxrestriction"; 160 161 /** 162 * Service name for {@link android.car.settings.CarConfigurationManager} 163 */ 164 public static final String CAR_CONFIGURATION_SERVICE = "configuration"; 165 166 /** 167 * @hide 168 */ 169 @SystemApi 170 public static final String STORAGE_MONITORING_SERVICE = "storage_monitoring"; 171 172 /** 173 * Service for testing. This is system app only feature. 174 * Service name for {@link CarTestManager}, to be used in {@link #getCarManager(String)}. 175 * @hide 176 */ 177 @SystemApi 178 public static final String TEST_SERVICE = "car-service-test"; 179 180 /** Permission necessary to access car's mileage information. 181 * @hide 182 */ 183 @SystemApi 184 public static final String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE"; 185 186 /** Permission necessary to access car's energy information. */ 187 public static final String PERMISSION_ENERGY = "android.car.permission.CAR_ENERGY"; 188 189 /** Permission necessary to access car's VIN information */ 190 public static final String PERMISSION_IDENTIFICATION = 191 "android.car.permission.CAR_IDENTIFICATION"; 192 193 /** Permission necessary to access car's speed. */ 194 public static final String PERMISSION_SPEED = "android.car.permission.CAR_SPEED"; 195 196 /** Permission necessary to access car's dynamics state. 197 * @hide 198 */ 199 @SystemApi 200 public static final String PERMISSION_CAR_DYNAMICS_STATE = 201 "android.car.permission.CAR_DYNAMICS_STATE"; 202 203 /** Permission necessary to access car's fuel door and ev charge port. */ 204 public static final String PERMISSION_ENERGY_PORTS = "android.car.permission.CAR_ENERGY_PORTS"; 205 206 /** Permission necessary to read car's lights information. 207 * @hide 208 */ 209 @SystemApi 210 public static final String PERMISSION_EXTERIOR_LIGHTS = 211 "android.car.permission.CAR_EXTERIOR_LIGHTS"; 212 213 /** Permission necessary to control car's exterior lights. 214 * @hide 215 */ 216 @SystemApi 217 public static final String PERMISSION_CONTROL_EXTERIOR_LIGHTS = 218 "android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS"; 219 220 /** Permission necessary to access car's powertrain information.*/ 221 public static final String PERMISSION_POWERTRAIN = "android.car.permission.CAR_POWERTRAIN"; 222 223 /** 224 * Permission necessary to change car audio volume through {@link CarAudioManager}. 225 */ 226 public static final String PERMISSION_CAR_CONTROL_AUDIO_VOLUME = 227 "android.car.permission.CAR_CONTROL_AUDIO_VOLUME"; 228 229 /** 230 * Permission necessary to change car audio settings through {@link CarAudioManager}. 231 * @hide 232 */ 233 public static final String PERMISSION_CAR_CONTROL_AUDIO_SETTINGS = 234 "android.car.permission.CAR_CONTROL_AUDIO_SETTINGS"; 235 236 /** 237 * Permission necessary to use {@link CarNavigationStatusManager}. 238 */ 239 public static final String PERMISSION_CAR_NAVIGATION_MANAGER = 240 "android.car.permission.CAR_NAVIGATION_MANAGER"; 241 242 /** 243 * Permission necessary to start activities in the instrument cluster through 244 * {@link CarInstrumentClusterManager} 245 * 246 * @hide 247 */ 248 @SystemApi 249 public static final String PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL = 250 "android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL"; 251 252 /** 253 * Application must have this permission in order to be launched in the instrument cluster 254 * display. 255 * 256 * @hide 257 */ 258 public static final String PERMISSION_CAR_DISPLAY_IN_CLUSTER = 259 "android.car.permission.CAR_DISPLAY_IN_CLUSTER"; 260 261 /** Permission necessary to use {@link CarInfoManager}. */ 262 public static final String PERMISSION_CAR_INFO = "android.car.permission.CAR_INFO"; 263 264 /** Permission necessary to read temperature of car's exterior environment. */ 265 public static final String PERMISSION_EXTERIOR_ENVIRONMENT = 266 "android.car.permission.CAR_EXTERIOR_ENVIRONMENT"; 267 268 /** 269 * Permission necessary to access car specific communication channel. 270 * @hide 271 */ 272 @SystemApi 273 public static final String PERMISSION_VENDOR_EXTENSION = 274 "android.car.permission.CAR_VENDOR_EXTENSION"; 275 276 /** 277 * @hide 278 */ 279 @SystemApi 280 public static final String PERMISSION_CONTROL_APP_BLOCKING = 281 "android.car.permission.CONTROL_APP_BLOCKING"; 282 283 /** 284 * Permission necessary to access Car Cabin APIs. 285 * @hide 286 */ 287 @SystemApi 288 public static final String PERMISSION_ADJUST_CAR_CABIN = 289 "android.car.permission.ADJUST_CAR_CABIN"; 290 291 /** 292 * Permission necessary to access car's engine information. 293 * @hide 294 */ 295 @SystemApi 296 public static final String PERMISSION_CAR_ENGINE_DETAILED = 297 "android.car.permission.CAR_ENGINE_DETAILED"; 298 299 /** 300 * Permission necessary to access car's tire pressure information. 301 * @hide 302 */ 303 @SystemApi 304 public static final String PERMISSION_TIRES = "android.car.permission.CAR_TIRES"; 305 306 /** 307 * Permission necessary to control car's door. 308 * @hide 309 */ 310 @SystemApi 311 public static final String PERMISSION_CONTROL_CAR_DOORS = 312 "android.car.permission.CONTROL_CAR_DOORS"; 313 314 /** 315 * Permission necessary to control car's windows. 316 * @hide 317 */ 318 @SystemApi 319 public static final String PERMISSION_CONTROL_CAR_WINDOWS = 320 "android.car.permission.CONTROL_CAR_WINDOWS"; 321 322 /** 323 * Permission necessary to control car's seats. 324 * @hide 325 */ 326 @SystemApi 327 public static final String PERMISSION_CONTROL_CAR_SEATS = 328 "android.car.permission.CONTROL_CAR_SEATS"; 329 330 /** 331 * Permission necessary to control car's mirrors. 332 * @hide 333 */ 334 @SystemApi 335 public static final String PERMISSION_CONTROL_CAR_MIRRORS = 336 "android.car.permission.CONTROL_CAR_MIRRORS"; 337 338 /** 339 * Permission necessary to access Car HVAC APIs. 340 * @hide 341 */ 342 @SystemApi 343 public static final String PERMISSION_CONTROL_CAR_CLIMATE = 344 "android.car.permission.CONTROL_CAR_CLIMATE"; 345 346 /** 347 * Permission necessary to access Car POWER APIs. 348 * @hide 349 */ 350 @SystemApi 351 public static final String PERMISSION_CAR_POWER = "android.car.permission.CAR_POWER"; 352 353 /** 354 * Permission necessary to access Car PROJECTION system APIs. 355 * @hide 356 */ 357 @SystemApi 358 public static final String PERMISSION_CAR_PROJECTION = "android.car.permission.CAR_PROJECTION"; 359 360 /** 361 * Permission necessary to mock vehicle hal for testing. 362 * @hide 363 * @deprecated mocking vehicle HAL in car service is no longer supported. 364 */ 365 @SystemApi 366 public static final String PERMISSION_MOCK_VEHICLE_HAL = 367 "android.car.permission.CAR_MOCK_VEHICLE_HAL"; 368 369 /** 370 * Permission necessary to access CarTestService. 371 * @hide 372 */ 373 @SystemApi 374 public static final String PERMISSION_CAR_TEST_SERVICE = 375 "android.car.permission.CAR_TEST_SERVICE"; 376 377 /** 378 * Permission necessary to access CarDrivingStateService to get a Car's driving state. 379 * @hide 380 */ 381 @SystemApi 382 public static final String PERMISSION_CAR_DRIVING_STATE = 383 "android.car.permission.CAR_DRIVING_STATE"; 384 385 /** 386 * Permissions necessary to access VMS publisher APIs. 387 * 388 * @hide 389 */ 390 @SystemApi 391 public static final String PERMISSION_VMS_PUBLISHER = "android.car.permission.VMS_PUBLISHER"; 392 393 /** 394 * Permissions necessary to access VMS subscriber APIs. 395 * 396 * @hide 397 */ 398 @SystemApi 399 public static final String PERMISSION_VMS_SUBSCRIBER = "android.car.permission.VMS_SUBSCRIBER"; 400 401 /** 402 * Permissions necessary to read diagnostic information, including vendor-specific bits. 403 * 404 * @hide 405 */ 406 @SystemApi 407 public static final String PERMISSION_CAR_DIAGNOSTIC_READ_ALL = 408 "android.car.permission.CAR_DIAGNOSTICS"; 409 410 /** 411 * Permissions necessary to clear diagnostic information. 412 * 413 * @hide 414 */ 415 @SystemApi 416 public static final String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.CLEAR_CAR_DIAGNOSTICS"; 417 418 /** 419 * Permissions necessary to clear diagnostic information. 420 * 421 * @hide 422 */ 423 @SystemApi 424 public static final String PERMISSION_STORAGE_MONITORING = "android.car.permission.STORAGE_MONITORING"; 425 426 /** Type of car connection: platform runs directly in car. */ 427 public static final int CONNECTION_TYPE_EMBEDDED = 5; 428 429 430 /** @hide */ 431 @IntDef({CONNECTION_TYPE_EMBEDDED}) 432 @Retention(RetentionPolicy.SOURCE) 433 public @interface ConnectionType {} 434 435 /** 436 * CarXyzService throws IllegalStateException with this message is re-thrown as 437 * {@link CarNotConnectedException}. 438 * 439 * @hide 440 */ 441 public static final String CAR_NOT_CONNECTED_EXCEPTION_MSG = "CarNotConnected"; 442 443 /** 444 * Activity Action: Provide media playing through a media template app. 445 * <p>Input: String extra mapped by {@link android.app.SearchManager#QUERY} is the query 446 * used to start the media. String extra mapped by {@link #CAR_EXTRA_MEDIA_PACKAGE} is the 447 * package name of the media app which user wants to play media on. 448 * <p>Output: nothing. 449 */ 450 public static final String CAR_INTENT_ACTION_MEDIA_TEMPLATE = 451 "android.car.intent.action.MEDIA_TEMPLATE"; 452 453 /** 454 * Used as a string extra field with {@link #CAR_INTENT_ACTION_MEDIA_TEMPLATE} to specify the 455 * media app that user wants to start the media on. Note: this is not the templated media app. 456 */ 457 public static final String CAR_EXTRA_MEDIA_PACKAGE = "android.car.intent.extra.MEDIA_PACKAGE"; 458 459 /** @hide */ 460 public static final String CAR_SERVICE_INTERFACE_NAME = "android.car.ICar"; 461 462 private static final String CAR_SERVICE_PACKAGE = "com.android.car"; 463 464 private static final String CAR_SERVICE_CLASS = "com.android.car.CarService"; 465 466 private static final long CAR_SERVICE_BIND_RETRY_INTERVAL_MS = 500; 467 private static final long CAR_SERVICE_BIND_MAX_RETRY = 20; 468 469 private final Context mContext; 470 @GuardedBy("this") 471 private ICar mService; 472 private final boolean mOwnsService; 473 private static final int STATE_DISCONNECTED = 0; 474 private static final int STATE_CONNECTING = 1; 475 private static final int STATE_CONNECTED = 2; 476 @GuardedBy("this") 477 private int mConnectionState; 478 @GuardedBy("this") 479 private int mConnectionRetryCount; 480 481 private final Runnable mConnectionRetryRunnable = new Runnable() { 482 @Override 483 public void run() { 484 startCarService(); 485 } 486 }; 487 488 private final Runnable mConnectionRetryFailedRunnable = new Runnable() { 489 @Override 490 public void run() { 491 mServiceConnectionListener.onServiceDisconnected(new ComponentName(CAR_SERVICE_PACKAGE, 492 CAR_SERVICE_CLASS)); 493 } 494 }; 495 496 private final ServiceConnection mServiceConnectionListener = 497 new ServiceConnection () { 498 public void onServiceConnected(ComponentName name, IBinder service) { 499 synchronized (Car.this) { 500 mService = ICar.Stub.asInterface(service); 501 mConnectionState = STATE_CONNECTED; 502 } 503 mServiceConnectionListenerClient.onServiceConnected(name, service); 504 } 505 506 public void onServiceDisconnected(ComponentName name) { 507 synchronized (Car.this) { 508 mService = null; 509 if (mConnectionState == STATE_DISCONNECTED) { 510 return; 511 } 512 mConnectionState = STATE_DISCONNECTED; 513 } 514 // unbind explicitly here. 515 disconnect(); 516 mServiceConnectionListenerClient.onServiceDisconnected(name); 517 } 518 }; 519 520 private final ServiceConnection mServiceConnectionListenerClient; 521 private final Object mCarManagerLock = new Object(); 522 @GuardedBy("mCarManagerLock") 523 private final HashMap<String, CarManagerBase> mServiceMap = new HashMap<>(); 524 525 /** Handler for generic event dispatching. */ 526 private final Handler mEventHandler; 527 528 private final Handler mMainThreadEventHandler; 529 530 /** 531 * A factory method that creates Car instance for all Car API access. 532 * @param context 533 * @param serviceConnectionListener listener for monitoring service connection. 534 * @param handler the handler on which the callback should execute, or null to execute on the 535 * service's main thread. Note: the service connection listener will be always on the main 536 * thread regardless of the handler given. 537 * @return Car instance if system is in car environment and returns {@code null} otherwise. 538 */ 539 public static Car createCar(Context context, ServiceConnection serviceConnectionListener, 540 @Nullable Handler handler) { 541 if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 542 Log.e(CarLibLog.TAG_CAR, "FEATURE_AUTOMOTIVE not declared while android.car is used"); 543 return null; 544 } 545 try { 546 return new Car(context, serviceConnectionListener, handler); 547 } catch (IllegalArgumentException e) { 548 // Expected when car service loader is not available. 549 } 550 return null; 551 } 552 553 /** 554 * A factory method that creates Car instance for all Car API access using main thread {@code 555 * Looper}. 556 * 557 * @see #createCar(Context, ServiceConnection, Handler) 558 */ 559 public static Car createCar(Context context, ServiceConnection serviceConnectionListener) { 560 return createCar(context, serviceConnectionListener, null); 561 } 562 563 private Car(Context context, ServiceConnection serviceConnectionListener, 564 @Nullable Handler handler) { 565 mContext = context; 566 mEventHandler = determineEventHandler(handler); 567 mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler); 568 569 mService = null; 570 mOwnsService = true; 571 mServiceConnectionListenerClient = serviceConnectionListener; 572 } 573 574 575 /** 576 * Car constructor when ICar binder is already available. 577 * @hide 578 */ 579 public Car(Context context, ICar service, @Nullable Handler handler) { 580 mContext = context; 581 mEventHandler = determineEventHandler(handler); 582 mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler); 583 584 mService = service; 585 mOwnsService = false; 586 mConnectionState = STATE_CONNECTED; 587 mServiceConnectionListenerClient = null; 588 } 589 590 private static Handler determineMainThreadEventHandler(Handler eventHandler) { 591 Looper mainLooper = Looper.getMainLooper(); 592 return (eventHandler.getLooper() == mainLooper) ? eventHandler : new Handler(mainLooper); 593 } 594 595 private static Handler determineEventHandler(@Nullable Handler handler) { 596 if (handler == null) { 597 Looper looper = Looper.getMainLooper(); 598 handler = new Handler(looper); 599 } 600 return handler; 601 } 602 603 /** 604 * Connect to car service. This can be called while it is disconnected. 605 * @throws IllegalStateException If connection is still on-going from previous 606 * connect call or it is already connected 607 */ 608 public void connect() throws IllegalStateException { 609 synchronized (this) { 610 if (mConnectionState != STATE_DISCONNECTED) { 611 throw new IllegalStateException("already connected or connecting"); 612 } 613 mConnectionState = STATE_CONNECTING; 614 startCarService(); 615 } 616 } 617 618 /** 619 * Disconnect from car service. This can be called while disconnected. Once disconnect is 620 * called, all Car*Managers from this instance becomes invalid, and 621 * {@link Car#getCarManager(String)} will return different instance if it is connected again. 622 */ 623 public void disconnect() { 624 synchronized (this) { 625 if (mConnectionState == STATE_DISCONNECTED) { 626 return; 627 } 628 mEventHandler.removeCallbacks(mConnectionRetryRunnable); 629 mMainThreadEventHandler.removeCallbacks(mConnectionRetryFailedRunnable); 630 mConnectionRetryCount = 0; 631 tearDownCarManagers(); 632 mService = null; 633 mConnectionState = STATE_DISCONNECTED; 634 635 if (mOwnsService) { 636 mContext.unbindService(mServiceConnectionListener); 637 } 638 } 639 } 640 641 /** 642 * Tells if it is connected to the service or not. This will return false if it is still 643 * connecting. 644 * @return 645 */ 646 public boolean isConnected() { 647 synchronized (this) { 648 return mService != null; 649 } 650 } 651 652 /** 653 * Tells if this instance is already connecting to car service or not. 654 * @return 655 */ 656 public boolean isConnecting() { 657 synchronized (this) { 658 return mConnectionState == STATE_CONNECTING; 659 } 660 } 661 662 /** 663 * Get car specific service as in {@link Context#getSystemService(String)}. Returned 664 * {@link Object} should be type-casted to the desired service. 665 * For example, to get sensor service, 666 * SensorManagerService sensorManagerService = car.getCarManager(Car.SENSOR_SERVICE); 667 * @param serviceName Name of service that should be created like {@link #SENSOR_SERVICE}. 668 * @return Matching service manager or null if there is no such service. 669 * @throws CarNotConnectedException if the connection to the car service has been lost. 670 */ 671 public Object getCarManager(String serviceName) throws CarNotConnectedException { 672 CarManagerBase manager; 673 ICar service = getICarOrThrow(); 674 synchronized (mCarManagerLock) { 675 manager = mServiceMap.get(serviceName); 676 if (manager == null) { 677 try { 678 IBinder binder = service.getCarService(serviceName); 679 if (binder == null) { 680 Log.w(CarLibLog.TAG_CAR, "getCarManager could not get binder for service:" + 681 serviceName); 682 return null; 683 } 684 manager = createCarManager(serviceName, binder); 685 if (manager == null) { 686 Log.w(CarLibLog.TAG_CAR, 687 "getCarManager could not create manager for service:" + 688 serviceName); 689 return null; 690 } 691 mServiceMap.put(serviceName, manager); 692 } catch (RemoteException e) { 693 handleRemoteException(e); 694 } 695 } 696 } 697 return manager; 698 } 699 700 /** 701 * Return the type of currently connected car. 702 * @return 703 */ 704 @ConnectionType 705 public int getCarConnectionType() { 706 return CONNECTION_TYPE_EMBEDDED; 707 } 708 709 /** 710 * IllegalStateException from XyzCarService with special message is re-thrown as a different 711 * exception. If the IllegalStateException is not understood then this message will throw the 712 * original exception. 713 * 714 * @param e exception from XyzCarService. 715 * @throws CarNotConnectedException if the connection to the car service has been lost. 716 * @hide 717 */ 718 public static void checkCarNotConnectedExceptionFromCarService( 719 IllegalStateException e) throws CarNotConnectedException, IllegalStateException { 720 String message = e.getMessage(); 721 if (CAR_NOT_CONNECTED_EXCEPTION_MSG.equals(message)) { 722 throw new CarNotConnectedException(); 723 } else { 724 throw e; 725 } 726 } 727 728 /** @hide */ 729 public static void hideCarNotConnectedExceptionFromCarService( 730 IllegalStateException e) throws IllegalStateException { 731 String message = e.getMessage(); 732 if (CAR_NOT_CONNECTED_EXCEPTION_MSG.equals(message)) { 733 return; //ignore 734 } else { 735 throw e; 736 } 737 } 738 739 private CarManagerBase createCarManager(String serviceName, IBinder binder) 740 throws CarNotConnectedException { 741 CarManagerBase manager = null; 742 switch (serviceName) { 743 case AUDIO_SERVICE: 744 manager = new CarAudioManager(binder, mContext, mEventHandler); 745 break; 746 case SENSOR_SERVICE: 747 manager = new CarSensorManager(binder, mContext, mEventHandler); 748 break; 749 case INFO_SERVICE: 750 manager = new CarInfoManager(binder); 751 break; 752 case APP_FOCUS_SERVICE: 753 manager = new CarAppFocusManager(binder, mEventHandler); 754 break; 755 case PACKAGE_SERVICE: 756 manager = new CarPackageManager(binder, mContext); 757 break; 758 case CAR_NAVIGATION_SERVICE: 759 manager = new CarNavigationStatusManager(binder); 760 break; 761 case CABIN_SERVICE: 762 manager = new CarCabinManager(binder, mContext, mEventHandler); 763 break; 764 case DIAGNOSTIC_SERVICE: 765 manager = new CarDiagnosticManager(binder, mContext, mEventHandler); 766 break; 767 case HVAC_SERVICE: 768 manager = new CarHvacManager(binder, mContext, mEventHandler); 769 break; 770 case POWER_SERVICE: 771 manager = new CarPowerManager(binder, mContext, mEventHandler); 772 break; 773 case PROJECTION_SERVICE: 774 manager = new CarProjectionManager(binder, mEventHandler); 775 break; 776 case PROPERTY_SERVICE: 777 manager = new CarPropertyManager(binder, mEventHandler, false, 778 "CarPropertyManager"); 779 break; 780 case VENDOR_EXTENSION_SERVICE: 781 manager = new CarVendorExtensionManager(binder, mEventHandler); 782 break; 783 case CAR_INSTRUMENT_CLUSTER_SERVICE: 784 manager = new CarInstrumentClusterManager(binder, mEventHandler); 785 break; 786 case TEST_SERVICE: 787 /* CarTestManager exist in static library. So instead of constructing it here, 788 * only pass binder wrapper so that CarTestManager can be constructed outside. */ 789 manager = new CarTestManagerBinderWrapper(binder); 790 break; 791 case VMS_SUBSCRIBER_SERVICE: 792 manager = new VmsSubscriberManager(binder); 793 break; 794 case BLUETOOTH_SERVICE: 795 manager = new CarBluetoothManager(binder, mContext); 796 break; 797 case STORAGE_MONITORING_SERVICE: 798 manager = new CarStorageMonitoringManager(binder, mEventHandler); 799 break; 800 case CAR_DRIVING_STATE_SERVICE: 801 manager = new CarDrivingStateManager(binder, mContext, mEventHandler); 802 break; 803 case CAR_UX_RESTRICTION_SERVICE: 804 manager = new CarUxRestrictionsManager(binder, mContext, mEventHandler); 805 break; 806 case CAR_CONFIGURATION_SERVICE: 807 manager = new CarConfigurationManager(binder); 808 break; 809 default: 810 break; 811 } 812 return manager; 813 } 814 815 private void startCarService() { 816 Intent intent = new Intent(); 817 intent.setPackage(CAR_SERVICE_PACKAGE); 818 intent.setAction(Car.CAR_SERVICE_INTERFACE_NAME); 819 boolean bound = mContext.bindServiceAsUser(intent, mServiceConnectionListener, 820 Context.BIND_AUTO_CREATE, UserHandle.CURRENT_OR_SELF); 821 if (!bound) { 822 mConnectionRetryCount++; 823 if (mConnectionRetryCount > CAR_SERVICE_BIND_MAX_RETRY) { 824 Log.w(CarLibLog.TAG_CAR, "cannot bind to car service after max retry"); 825 mMainThreadEventHandler.post(mConnectionRetryFailedRunnable); 826 } else { 827 mEventHandler.postDelayed(mConnectionRetryRunnable, 828 CAR_SERVICE_BIND_RETRY_INTERVAL_MS); 829 } 830 } else { 831 mConnectionRetryCount = 0; 832 } 833 } 834 835 private synchronized ICar getICarOrThrow() throws IllegalStateException { 836 if (mService == null) { 837 throw new IllegalStateException("not connected"); 838 } 839 return mService; 840 } 841 842 private void handleRemoteException(RemoteException e) { 843 Log.w(CarLibLog.TAG_CAR, "RemoteException", e); 844 disconnect(); 845 } 846 847 private void tearDownCarManagers() { 848 synchronized (mCarManagerLock) { 849 for (CarManagerBase manager: mServiceMap.values()) { 850 manager.onCarDisconnected(); 851 } 852 mServiceMap.clear(); 853 } 854 } 855 } 856