1 /* 2 * Copyright (C) 2022 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.oem; 18 19 import android.annotation.Nullable; 20 import android.car.builtin.content.pm.PackageManagerHelper; 21 import android.car.builtin.os.BuildHelper; 22 import android.car.builtin.os.TraceHelper; 23 import android.car.builtin.util.Slogf; 24 import android.car.builtin.util.TimingsTraceLog; 25 import android.car.oem.IOemCarAudioDuckingService; 26 import android.car.oem.IOemCarAudioFocusService; 27 import android.car.oem.IOemCarAudioVolumeService; 28 import android.car.oem.IOemCarService; 29 import android.car.oem.IOemCarServiceCallback; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.ServiceConnection; 34 import android.content.pm.PackageInfo; 35 import android.content.pm.PackageManager.NameNotFoundException; 36 import android.content.res.Resources; 37 import android.os.Binder; 38 import android.os.Handler; 39 import android.os.HandlerThread; 40 import android.os.IBinder; 41 import android.os.RemoteException; 42 import android.os.SystemClock; 43 import android.os.SystemProperties; 44 import android.os.UserHandle; 45 import android.text.TextUtils; 46 import android.util.Log; 47 48 import com.android.car.CarServiceBase; 49 import com.android.car.CarServiceUtils; 50 import com.android.car.R; 51 import com.android.car.internal.util.IndentingPrintWriter; 52 import com.android.internal.annotations.GuardedBy; 53 import com.android.internal.annotations.VisibleForTesting; 54 55 import java.util.ArrayList; 56 import java.util.concurrent.CountDownLatch; 57 import java.util.concurrent.TimeUnit; 58 import java.util.concurrent.TimeoutException; 59 60 /** 61 * Manages access to OemCarService. 62 * 63 * <p>All calls in this class are blocking on OEM service initialization, so should be called as 64 * late as possible. 65 * 66 * <b>NOTE</b>: All {@link CarOemProxyService} call should be after init of ICarImpl. If any 67 * component calls {@link CarOemProxyService} before init of ICarImpl complete, it would throw 68 * {@link IllegalStateException}. 69 */ 70 public final class CarOemProxyService implements CarServiceBase { 71 72 private static final String TAG = CarOemProxyService.class.getSimpleName(); 73 private static final String CALL_TAG = CarOemProxyService.class.getSimpleName(); 74 private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG); 75 // mock component name for testing if system property is set. 76 private static final String PROPERTY_EMULATED_OEM_CAR_SERVICE = 77 "persist.com.android.car.internal.debug.oem_car_service"; 78 79 private final int mOemServiceConnectionTimeoutMs; 80 private final int mOemServiceReadyTimeoutMs; 81 private final Object mLock = new Object(); 82 private final boolean mIsFeatureEnabled; 83 private final Context mContext; 84 private final boolean mIsOemServiceBound; 85 private final CarOemProxyServiceHelper mHelper; 86 private final HandlerThread mHandlerThread; 87 private final Handler mHandler; 88 @GuardedBy("mLock") 89 private final ArrayList<CarOemProxyServiceCallback> mCallbacks = new ArrayList<>(); 90 91 92 private String mComponentName; 93 94 // True once OemService return true for {@code isOemServiceReady} call. It means that OEM 95 // service has completed all the initialization and ready to serve requests. 96 @GuardedBy("mLock") 97 private boolean mIsOemServiceReady; 98 // True once OEM service is connected. It means that OEM service has return binder for 99 // communication. OEM service may still not be ready. 100 @GuardedBy("mLock") 101 private boolean mIsOemServiceConnected; 102 103 @GuardedBy("mLock") 104 private boolean mInitComplete; 105 @GuardedBy("mLock") 106 private IOemCarService mOemCarService; 107 @GuardedBy("mLock") 108 private CarOemAudioFocusProxyService mCarOemAudioFocusProxyService; 109 @GuardedBy("mLock") 110 private CarOemAudioVolumeProxyService mCarOemAudioVolumeProxyService; 111 @GuardedBy("mLock") 112 private CarOemAudioDuckingProxyService mCarOemAudioDuckingProxyService; 113 private long mWaitForOemServiceConnectedDuration; 114 private long mWaitForOemServiceReadyDuration; 115 116 117 private final ServiceConnection mCarOemServiceConnection = new ServiceConnection() { 118 119 @Override 120 public void onServiceConnected(ComponentName componentName, IBinder iBinder) { 121 Slogf.i(TAG, "onServiceConnected: %s, %s", componentName, iBinder); 122 synchronized (mLock) { 123 if (mOemCarService == IOemCarService.Stub.asInterface(iBinder)) { 124 return; // already connected. 125 } 126 Slogf.i(TAG, "car oem service binder changed, was %s now: %s", 127 mOemCarService, iBinder); 128 mOemCarService = IOemCarService.Stub.asInterface(iBinder); 129 Slogf.i(TAG, "**CarOemService connected**"); 130 mIsOemServiceConnected = true; 131 mLock.notifyAll(); 132 } 133 } 134 135 @Override 136 public void onServiceDisconnected(ComponentName componentName) { 137 Slogf.e(TAG, "OEM service crashed. Crashing the CarService. ComponentName:%s", 138 componentName); 139 mHelper.crashCarService("Service Disconnected"); 140 } 141 }; 142 143 private final CountDownLatch mOemServiceReadyLatch = new CountDownLatch(1); 144 145 private final IOemCarServiceCallback mOemCarServiceCallback = new IOemCarServiceCallbackImpl(); 146 147 @VisibleForTesting CarOemProxyService(Context context)148 public CarOemProxyService(Context context) { 149 this(context, null); 150 } 151 152 @VisibleForTesting CarOemProxyService(Context context, CarOemProxyServiceHelper helper)153 public CarOemProxyService(Context context, CarOemProxyServiceHelper helper) { 154 this(context, helper, null); 155 } 156 CarOemProxyService(Context context, CarOemProxyServiceHelper helper, Handler handler)157 public CarOemProxyService(Context context, CarOemProxyServiceHelper helper, Handler handler) { 158 // Bind to the OemCarService 159 mContext = context; 160 Resources res = mContext.getResources(); 161 mOemServiceConnectionTimeoutMs = res 162 .getInteger(R.integer.config_oemCarService_connection_timeout_ms); 163 mOemServiceReadyTimeoutMs = res 164 .getInteger(R.integer.config_oemCarService_serviceReady_timeout_ms); 165 166 String componentName = res.getString(R.string.config_oemCarService); 167 168 if (TextUtils.isEmpty(componentName)) { 169 // mock component name for testing if system property is set. 170 String emulatedOemCarService = SystemProperties.get(PROPERTY_EMULATED_OEM_CAR_SERVICE, 171 ""); 172 if (!BuildHelper.isUserBuild() && emulatedOemCarService != null 173 && !emulatedOemCarService.isEmpty()) { 174 componentName = emulatedOemCarService; 175 Slogf.i(TAG, "Using emulated componentname for testing. ComponentName: %s", 176 mComponentName); 177 } 178 } 179 180 mComponentName = componentName; 181 182 Slogf.i(TAG, "Oem Car Service Config. Connection timeout:%s, Service Ready timeout:%d, " 183 + "component Name:%s", mOemServiceConnectionTimeoutMs, mOemServiceReadyTimeoutMs, 184 mComponentName); 185 186 if (isInvalidComponentName(context, mComponentName)) { 187 // feature disabled 188 mIsFeatureEnabled = false; 189 mIsOemServiceBound = false; 190 mHelper = null; 191 mHandlerThread = null; 192 mHandler = null; 193 Slogf.i(TAG, "**CarOemService is disabled.**"); 194 return; 195 } 196 197 Intent intent = (new Intent()) 198 .setComponent(ComponentName.unflattenFromString(mComponentName)); 199 200 Slogf.i(TAG, "Binding to Oem Service with intent: %s", intent); 201 mHandlerThread = CarServiceUtils.getHandlerThread("car_oem_service"); 202 mHandler = handler == null ? new Handler(mHandlerThread.getLooper()) : handler; 203 204 mIsOemServiceBound = mContext.bindServiceAsUser(intent, mCarOemServiceConnection, 205 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM); 206 207 if (mIsOemServiceBound) { 208 mIsFeatureEnabled = true; 209 Slogf.i(TAG, "OemCarService bounded."); 210 } else { 211 mIsFeatureEnabled = false; 212 Slogf.e(TAG, 213 "Couldn't bound to OemCarService. Oem service feature is marked disabled."); 214 } 215 mHelper = helper == null ? new CarOemProxyServiceHelper(mContext) : helper; 216 } 217 isInvalidComponentName(Context context, String componentName)218 private boolean isInvalidComponentName(Context context, String componentName) { 219 if (componentName == null || componentName.isEmpty()) { 220 if (DBG) { 221 Slogf.d(TAG, "ComponentName is null or empty."); 222 } 223 return true; 224 } 225 226 // Only pre-installed package can be used for OEM Service. 227 String packageName = ComponentName.unflattenFromString(componentName).getPackageName(); 228 PackageInfo info; 229 try { 230 info = context.getPackageManager().getPackageInfo(packageName, /* flags= */ 0); 231 } catch (NameNotFoundException e) { 232 Slogf.e(TAG, "componentName %s not found.", componentName); 233 return true; 234 } 235 236 if (info == null || info.applicationInfo == null 237 || !(PackageManagerHelper.isSystemApp(info.applicationInfo) 238 || PackageManagerHelper.isUpdatedSystemApp(info.applicationInfo) 239 || PackageManagerHelper.isOemApp(info.applicationInfo) 240 || PackageManagerHelper.isOdmApp(info.applicationInfo) 241 || PackageManagerHelper.isVendorApp(info.applicationInfo) 242 || PackageManagerHelper.isProductApp(info.applicationInfo) 243 || PackageManagerHelper.isSystemExtApp(info.applicationInfo))) { 244 if (DBG) { 245 Slogf.d(TAG, "Invalid component name. Info: %s", info); 246 } 247 return true; 248 } 249 250 if (DBG) { 251 Slogf.d(TAG, "Valid component name %s, ", componentName); 252 } 253 254 return false; 255 } 256 257 /** 258 * Registers callback to be called once OEM service is ready. 259 * 260 * <p>Other CarService components cannot call OEM service. But they can register a callback 261 * which would be called as soon as OEM Service is ready./ 262 */ registerCallback(CarOemProxyServiceCallback callback)263 public void registerCallback(CarOemProxyServiceCallback callback) { 264 synchronized (mLock) { 265 mCallbacks.add(callback); 266 } 267 } 268 269 /** 270 * Informs if OEM service is enabled. 271 */ isOemServiceEnabled()272 public boolean isOemServiceEnabled() { 273 synchronized (mLock) { 274 return mIsFeatureEnabled; 275 } 276 } 277 278 /** 279 * Informs if OEM service is ready. 280 */ isOemServiceReady()281 public boolean isOemServiceReady() { 282 synchronized (mLock) { 283 return mIsOemServiceReady; 284 } 285 } 286 287 @Override init()288 public void init() { 289 // Nothing to be done as OemCarService was initialized in the constructor. 290 } 291 292 @Override release()293 public void release() { 294 // Stop OEM Service; 295 if (mIsOemServiceBound) { 296 Slogf.i(TAG, "Unbinding Oem Service"); 297 mContext.unbindService(mCarOemServiceConnection); 298 } 299 } 300 301 @Override dump(IndentingPrintWriter writer)302 public void dump(IndentingPrintWriter writer) { 303 writer.println("***CarOemProxyService dump***"); 304 writer.increaseIndent(); 305 synchronized (mLock) { 306 writer.printf("mIsFeatureEnabled: %s\n", mIsFeatureEnabled); 307 writer.printf("mIsOemServiceBound: %s\n", mIsOemServiceBound); 308 writer.printf("mIsOemServiceReady: %s\n", mIsOemServiceReady); 309 writer.printf("mIsOemServiceConnected: %s\n", mIsOemServiceConnected); 310 writer.printf("mInitComplete: %s\n", mInitComplete); 311 writer.printf("OEM_CAR_SERVICE_CONNECTED_TIMEOUT_MS: %s\n", 312 mOemServiceConnectionTimeoutMs); 313 writer.printf("OEM_CAR_SERVICE_READY_TIMEOUT_MS: %s\n", mOemServiceReadyTimeoutMs); 314 writer.printf("mComponentName: %s\n", mComponentName); 315 writer.printf("waitForOemServiceConnected completed in : %d ms\n", 316 mWaitForOemServiceConnectedDuration); 317 writer.printf("waitForOemServiceReady completed in : %d ms\n", 318 mWaitForOemServiceReadyDuration); 319 // Dump other service components. 320 getCarOemAudioFocusService().dump(writer); 321 getCarOemAudioVolumeService().dump(writer); 322 // Dump OEM service stack 323 if (mIsOemServiceReady) { 324 writer.printf("OEM callstack\n"); 325 int timeoutMs = 2000; 326 try { 327 IOemCarService oemCarService = getOemService(); 328 writer.printf(mHelper.doBinderTimedCallWithTimeout(CALL_TAG, 329 () -> oemCarService.getAllStackTraces(), timeoutMs)); 330 } catch (TimeoutException e) { 331 writer.printf("Didn't received OEM stack within %d milliseconds.\n", timeoutMs); 332 } 333 } 334 // Dump helper 335 if (mHelper != null) { 336 mHelper.dump(writer); 337 } 338 } 339 writer.decreaseIndent(); 340 } 341 getOemServiceName()342 public String getOemServiceName() { 343 return mComponentName; 344 } 345 346 /** 347 * Gets OEM audio focus service. 348 */ 349 @Nullable getCarOemAudioFocusService()350 public CarOemAudioFocusProxyService getCarOemAudioFocusService() { 351 if (!mIsFeatureEnabled) { 352 if (DBG) { 353 Slogf.d(TAG, "Oem Car Service is disabled, returning null for" 354 + " getCarOemAudioFocusService"); 355 } 356 return null; 357 } 358 359 synchronized (mLock) { 360 if (mCarOemAudioFocusProxyService != null) { 361 return mCarOemAudioFocusProxyService; 362 } 363 } 364 365 waitForOemService(); 366 367 // Defaults to returning null service and try again next time the service is requested. 368 IOemCarService oemCarService = getOemService(); 369 IOemCarAudioFocusService oemAudioFocusService = mHelper.doBinderTimedCallWithDefaultValue( 370 CALL_TAG, () -> oemCarService.getOemAudioFocusService(), 371 /* defaultValue= */ null); 372 373 if (oemAudioFocusService == null) { 374 if (DBG) { 375 Slogf.d(TAG, "Oem Car Service doesn't implement AudioFocusService, returning null" 376 + " for getCarOemAudioFocusService"); 377 } 378 return null; 379 } 380 381 CarOemAudioFocusProxyService carOemAudioFocusProxyService = 382 new CarOemAudioFocusProxyService(mHelper, oemAudioFocusService); 383 synchronized (mLock) { 384 if (mCarOemAudioFocusProxyService != null) { 385 return mCarOemAudioFocusProxyService; 386 } 387 mCarOemAudioFocusProxyService = carOemAudioFocusProxyService; 388 Slogf.i(TAG, "CarOemAudioFocusProxyService is ready."); 389 return mCarOemAudioFocusProxyService; 390 } 391 } 392 393 /** 394 * Gets OEM audio volume service. 395 */ 396 @Nullable getCarOemAudioVolumeService()397 public CarOemAudioVolumeProxyService getCarOemAudioVolumeService() { 398 if (!mIsFeatureEnabled) { 399 if (DBG) { 400 Slogf.d(TAG, "Oem Car Service is disabled, returning null for" 401 + " getCarOemAudioVolumeService"); 402 } 403 return null; 404 } 405 406 synchronized (mLock) { 407 if (mCarOemAudioVolumeProxyService != null) { 408 return mCarOemAudioVolumeProxyService; 409 } 410 } 411 412 waitForOemService(); 413 IOemCarService oemCarService = getOemService(); 414 IOemCarAudioVolumeService oemAudioVolumeService = mHelper.doBinderTimedCallWithDefaultValue( 415 CALL_TAG, () -> oemCarService.getOemAudioVolumeService(), 416 /* defaultValue= */ null); 417 418 if (oemAudioVolumeService == null) { 419 if (DBG) { 420 Slogf.d(TAG, "Oem Car Service doesn't implement AudioVolumeService," 421 + "returning null for getCarOemAudioDuckingService"); 422 } 423 return null; 424 } 425 426 CarOemAudioVolumeProxyService carOemAudioVolumeProxyService = 427 new CarOemAudioVolumeProxyService(mHelper, oemAudioVolumeService); 428 synchronized (mLock) { 429 if (mCarOemAudioVolumeProxyService != null) { 430 return mCarOemAudioVolumeProxyService; 431 } 432 mCarOemAudioVolumeProxyService = carOemAudioVolumeProxyService; 433 Slogf.i(TAG, "CarOemAudioVolumeProxyService is ready."); 434 } 435 return carOemAudioVolumeProxyService; 436 } 437 438 /** 439 * Gets OEM audio ducking service. 440 */ 441 @Nullable getCarOemAudioDuckingService()442 public CarOemAudioDuckingProxyService getCarOemAudioDuckingService() { 443 if (!mIsFeatureEnabled) { 444 if (DBG) { 445 Slogf.d(TAG, "Oem Car Service is disabled, returning null for" 446 + " getCarOemAudioDuckingService"); 447 } 448 return null; 449 } 450 451 synchronized (mLock) { 452 if (mCarOemAudioDuckingProxyService != null) { 453 return mCarOemAudioDuckingProxyService; 454 } 455 } 456 457 waitForOemService(); 458 459 IOemCarService oemCarService = getOemService(); 460 IOemCarAudioDuckingService oemAudioDuckingService = 461 mHelper.doBinderTimedCallWithDefaultValue( 462 CALL_TAG, () -> oemCarService.getOemAudioDuckingService(), 463 /* defaultValue= */ null); 464 465 if (oemAudioDuckingService == null) { 466 if (DBG) { 467 Slogf.d(TAG, "Oem Car Service doesn't implement AudioDuckingService," 468 + "returning null for getCarOemAudioDuckingService"); 469 } 470 return null; 471 } 472 473 CarOemAudioDuckingProxyService carOemAudioDuckingProxyService = 474 new CarOemAudioDuckingProxyService(mHelper, oemAudioDuckingService); 475 synchronized (mLock) { 476 if (mCarOemAudioDuckingProxyService != null) { 477 return mCarOemAudioDuckingProxyService; 478 } 479 mCarOemAudioDuckingProxyService = carOemAudioDuckingProxyService; 480 Slogf.i(TAG, "CarOemAudioDuckingProxyService is ready."); 481 } 482 return carOemAudioDuckingProxyService; 483 } 484 485 /** 486 * Should be called when CarService is ready for communication. It updates the OEM service that 487 * CarService is ready. 488 */ onCarServiceReady()489 public void onCarServiceReady() { 490 TimingsTraceLog t = new TimingsTraceLog(TAG, TraceHelper.TRACE_TAG_CAR_SERVICE); 491 long startTime = SystemClock.uptimeMillis(); 492 t.traceBegin("waitForOemServiceConnected"); 493 waitForOemServiceConnected(); 494 mWaitForOemServiceConnectedDuration = SystemClock.uptimeMillis() - startTime; 495 t.traceEnd(); 496 497 IOemCarService oemCarService = getOemService(); 498 mHelper.doBinderOneWayCall(CALL_TAG, () -> { 499 try { 500 oemCarService.onCarServiceReady(mOemCarServiceCallback); 501 } catch (RemoteException ex) { 502 Slogf.e(TAG, "Binder call received RemoteException, calling to crash CarService", 503 ex); 504 } 505 }); 506 507 t.traceBegin("waitForOemServiceReady"); 508 startTime = SystemClock.uptimeMillis(); 509 waitForOemServiceReady(); 510 mWaitForOemServiceReadyDuration = SystemClock.uptimeMillis() - startTime; 511 t.traceEnd(); 512 } 513 waitForOemServiceConnected()514 private void waitForOemServiceConnected() { 515 synchronized (mLock) { 516 if (!mInitComplete) { 517 // No CarOemService call should be made before or during init of ICarImpl. 518 throw new IllegalStateException( 519 "CarOemService should not be call before CarService initialization"); 520 } 521 522 if (mIsOemServiceConnected) { 523 return; 524 } 525 waitForOemServiceConnectedLocked(); 526 } 527 } 528 529 @GuardedBy("mLock") waitForOemServiceConnectedLocked()530 private void waitForOemServiceConnectedLocked() { 531 long startTime = SystemClock.elapsedRealtime(); 532 long remainingTime = mOemServiceConnectionTimeoutMs; 533 534 while (!mIsOemServiceConnected && remainingTime > 0) { 535 try { 536 Slogf.i(TAG, "waiting to connect to OemService. wait time: %s", remainingTime); 537 mLock.wait(mOemServiceConnectionTimeoutMs); 538 remainingTime = mOemServiceConnectionTimeoutMs 539 - (SystemClock.elapsedRealtime() - startTime); 540 } catch (InterruptedException e) { 541 Thread.currentThread().interrupt(); 542 Slogf.w(TAG, "InterruptedException received. Reset interrupted status.", e); 543 } 544 } 545 546 if (!mIsOemServiceConnected) { 547 Slogf.e(TAG, "OEM Service is not connected within: %dms, calling to crash CarService", 548 mOemServiceConnectionTimeoutMs); 549 mHelper.crashCarService("OEM Service not connected"); 550 } 551 } 552 waitForOemService()553 private void waitForOemService() { 554 waitForOemServiceConnected(); 555 waitForOemServiceReady(); 556 } 557 waitForOemServiceReady()558 private void waitForOemServiceReady() { 559 synchronized (mLock) { 560 if (mIsOemServiceReady) { 561 return; 562 } 563 } 564 565 try { 566 mOemServiceReadyLatch.await(mOemServiceReadyTimeoutMs, TimeUnit.MILLISECONDS); 567 } catch (InterruptedException e) { 568 Thread.currentThread().interrupt(); 569 Slogf.i(TAG, "Exception while waiting for OEM Service to be ready.", e); 570 } 571 572 synchronized (mLock) { 573 if (!mIsOemServiceReady) { 574 Slogf.e(TAG, "OEM Service is not ready within: " + mOemServiceReadyTimeoutMs 575 + "ms, calling to crash CarService"); 576 mHelper.crashCarService("OEM Service not ready"); 577 } 578 } 579 Slogf.i(TAG, "OEM Service is ready."); 580 } 581 582 // Initialize all OEM related components. initOemServiceComponents()583 private void initOemServiceComponents() { 584 // Initialize all Oem Service components 585 getCarOemAudioFocusService(); 586 587 // Callback registered Car Service components for OEM service. 588 callCarServiceComponents(); 589 } 590 callCarServiceComponents()591 private void callCarServiceComponents() { 592 synchronized (mLock) { 593 for (int i = 0; i < mCallbacks.size(); i++) { 594 mCallbacks.get(i).onOemServiceReady(); 595 } 596 } 597 } 598 599 /** 600 * Informs CarOemService that ICarImpl's init is complete. 601 */ 602 // This would set mInitComplete, which is an additional check so that no car service component 603 // calls CarOemService during or before ICarImpl's init. onInitComplete()604 public void onInitComplete() { 605 if (!mIsFeatureEnabled) { 606 if (DBG) { 607 Slogf.d(TAG, "Oem Car Service is disabled, No-op for onInitComplete"); 608 } 609 return; 610 } 611 612 synchronized (mLock) { 613 mInitComplete = true; 614 } 615 // inform OEM Service that CarService is ready for communication. 616 // It has to be posted on the different thread as this call is part of init process. 617 mHandler.post(() -> onCarServiceReady()); 618 } 619 620 /** 621 * Gets OEM service latest binder. Don't pass the method to helper as it can cause deadlock. 622 */ getOemService()623 private IOemCarService getOemService() { 624 synchronized (mLock) { 625 return mOemCarService; 626 } 627 } 628 629 private class IOemCarServiceCallbackImpl extends IOemCarServiceCallback.Stub { 630 @Override sendOemCarServiceReady()631 public void sendOemCarServiceReady() { 632 synchronized (mLock) { 633 mIsOemServiceReady = true; 634 } 635 mOemServiceReadyLatch.countDown(); 636 int pid = Binder.getCallingPid(); 637 Slogf.i(TAG, "OEM Car service is ready and running. Process ID of OEM Car Service is:" 638 + " %d", pid); 639 mHelper.updateOemPid(pid); 640 IOemCarService oemCarService = getOemService(); 641 mHelper.updateOemStackCall(() -> oemCarService.getAllStackTraces()); 642 // Initialize other components on handler thread so that main thread is not 643 // blocked 644 mHandler.post(() -> initOemServiceComponents()); 645 } 646 } 647 } 648