1ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung/* 2ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Copyright (C) 2015 The Android Open Source Project 3ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * 4ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Licensed under the Apache License, Version 2.0 (the "License"); 5ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * you may not use this file except in compliance with the License. 6ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * You may obtain a copy of the License at 7ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * 8ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * http://www.apache.org/licenses/LICENSE-2.0 9ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * 10ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Unless required by applicable law or agreed to in writing, software 11ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * distributed under the License is distributed on an "AS IS" BASIS, 12ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * See the License for the specific language governing permissions and 14ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * limitations under the License. 15ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung */ 16bf0eab7a275edfbf7df2881ebca69cde72bd5614Ram Periathiruvadi 17ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungpackage com.android.car; 18ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung 190d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport static android.os.SystemClock.elapsedRealtime; 200d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev 210d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.annotation.Nullable; 22ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.app.Service; 23ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.content.Intent; 24e33f07e7c149ae6bf9154745fd9f83b49127b4f7Yao Chenimport android.content.pm.PackageManager; 25cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.IVehicle; 26e33f07e7c149ae6bf9154745fd9f83b49127b4f7Yao Chenimport android.os.Binder; 27ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsevimport android.os.Build; 28ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.IBinder; 29ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsevimport android.os.IHwBinder.DeathRecipient; 301552204b9ebedb96dfb44c68ad519ef27c1d3c99Steven Morelandimport android.os.RemoteException; 31b40de197fb9b60bcbb20c243ba6b1a41e25e2e67Steve Paikimport android.os.ServiceManager; 32ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsevimport android.os.SystemClock; 33973d2a26ddab3d7752fa0385da4f53f8f721bfc8Vitalii Tomkivimport android.os.SystemProperties; 34ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.util.Log; 35ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung 36b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granataimport com.android.car.systeminterface.SystemInterface; 37b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata 38ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsevimport com.android.internal.annotations.VisibleForTesting; 39ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsevimport com.android.internal.util.RingBufferIndices; 40ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 41e33f07e7c149ae6bf9154745fd9f83b49127b4f7Yao Chenimport java.io.FileDescriptor; 42e33f07e7c149ae6bf9154745fd9f83b49127b4f7Yao Chenimport java.io.PrintWriter; 43ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsevimport java.util.NoSuchElementException; 44e33f07e7c149ae6bf9154745fd9f83b49127b4f7Yao Chen 45ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungpublic class CarService extends Service { 46ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung 470d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev private static final long WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS = 10_000; 480d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev 49ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE); 50ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 51ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private CanBusErrorNotifier mCanBusErrorNotifier; 52ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung private ICarImpl mICarImpl; 53ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private IVehicle mVehicle; 54ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 552cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev private String mVehicleInterfaceName; 562cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev 57ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev // If 10 crashes of Vehicle HAL occurred within 10 minutes then thrown an exception in 58ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev // Car Service. 59ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private final CrashTracker mVhalCrashTracker = new CrashTracker( 60ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 10, // Max crash count. 61ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 10 * 60 * 1000, // 10 minutes - sliding time window. 62ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev () -> { 63ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev if (IS_USER_BUILD) { 64ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev Log.e(CarLog.TAG_SERVICE, "Vehicle HAL keeps crashing, notifying user..."); 65ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCanBusErrorNotifier.reportFailure(CarService.this); 66ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } else { 67ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev throw new RuntimeException( 68ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev "Vehicle HAL crashed too many times in a given time frame"); 69ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 70ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 71ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev ); 72ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 73ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private final VehicleDeathRecipient mVehicleDeathRecipient = new VehicleDeathRecipient(); 74ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung 75ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung @Override 76ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung public void onCreate() { 77ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung Log.i(CarLog.TAG_SERVICE, "Service onCreate"); 78ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCanBusErrorNotifier = new CanBusErrorNotifier(this /* context */); 7999e1a7555a9521c33203b68c5ab5bd1c039ee712Pavel Maltsev mVehicle = getVehicle(); 802cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev 81ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev if (mVehicle == null) { 820d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev throw new IllegalStateException("Vehicle HAL service is not available."); 830d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev } 842cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev try { 852cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev mVehicleInterfaceName = mVehicle.interfaceDescriptor(); 862cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev } catch (RemoteException e) { 872cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev throw new IllegalStateException("Unable to get Vehicle HAL interface descriptor", e); 882cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev } 892cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev 902cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev Log.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName); 910d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev 92b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata mICarImpl = new ICarImpl(this, 93b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata mVehicle, 94b19bc326413285806ecca7fb7b54ec7a9074f286Enrico Granata SystemInterface.Builder.defaultSystemInterface(this).build(), 95e8056ca93515f01f237290bbc371bc082570fa96Enrico Granata mCanBusErrorNotifier, 96e8056ca93515f01f237290bbc371bc082570fa96Enrico Granata mVehicleInterfaceName); 970d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev mICarImpl.init(); 98973d2a26ddab3d7752fa0385da4f53f8f721bfc8Vitalii Tomkiv SystemProperties.set("boot.car_service_created", "1"); 99ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 100ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev linkToDeath(mVehicle, mVehicleDeathRecipient); 101ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 102b40de197fb9b60bcbb20c243ba6b1a41e25e2e67Steve Paik ServiceManager.addService("car_service", mICarImpl); 103ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung super.onCreate(); 104ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung } 105ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung 1069a916d707c04d80e9df6dcd84d976900804be717Enrico Granata // onDestroy is best-effort and might not get called on shutdown/reboot. As such it is not 1079a916d707c04d80e9df6dcd84d976900804be717Enrico Granata // suitable for permanently saving state or other need-to-happen operation. If you have a 1089a916d707c04d80e9df6dcd84d976900804be717Enrico Granata // cleanup task that you want to make sure happens on shutdown/reboot, see OnShutdownReboot. 109ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung @Override 110ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung public void onDestroy() { 111ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung Log.i(CarLog.TAG_SERVICE, "Service onDestroy"); 1120d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev mICarImpl.release(); 113ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCanBusErrorNotifier.removeFailureReport(this); 114ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 115ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev if (mVehicle != null) { 116ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev try { 117ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mVehicle.unlinkToDeath(mVehicleDeathRecipient); 118ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mVehicle = null; 119ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } catch (RemoteException e) { 120ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev // Ignore errors on shutdown path. 121ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 122ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 123ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 124ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung super.onDestroy(); 125ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung } 126ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung 127ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung @Override 128ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung public int onStartCommand(Intent intent, int flags, int startId) { 129ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung // keep it alive. 130ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung return START_STICKY; 131ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung } 132ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung 133ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung @Override 134ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung public IBinder onBind(Intent intent) { 135ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung return mICarImpl; 136ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung } 137ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung 138ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung @Override 139ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 140e8056ca93515f01f237290bbc371bc082570fa96Enrico Granata // historically, the way to get a dumpsys from CarService has been to use 141e8056ca93515f01f237290bbc371bc082570fa96Enrico Granata // "dumpsys activity service com.android.car/.CarService" - leaving this 142e8056ca93515f01f237290bbc371bc082570fa96Enrico Granata // as a forward to car_service makes the previously well-known command still work 143e8056ca93515f01f237290bbc371bc082570fa96Enrico Granata mICarImpl.dump(fd, writer, args); 144ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung } 1450d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev 1460d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev @Nullable 14799e1a7555a9521c33203b68c5ab5bd1c039ee712Pavel Maltsev private IVehicle getVehicleWithTimeout(long waitMilliseconds) { 14899e1a7555a9521c33203b68c5ab5bd1c039ee712Pavel Maltsev IVehicle vehicle = getVehicle(); 1490d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev long start = elapsedRealtime(); 1500d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev while (vehicle == null && (start + waitMilliseconds) > elapsedRealtime()) { 1510d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev try { 1520d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev Thread.sleep(100); 1530d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev } catch (InterruptedException e) { 1540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev throw new RuntimeException("Sleep was interrupted", e); 1550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev } 1560d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev 15799e1a7555a9521c33203b68c5ab5bd1c039ee712Pavel Maltsev vehicle = getVehicle(); 1580d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev } 159ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 160ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev if (vehicle != null) { 161ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCanBusErrorNotifier.removeFailureReport(this); 162ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 163ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 1640d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev return vehicle; 1650d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev } 1660d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev 1670d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev @Nullable 16899e1a7555a9521c33203b68c5ab5bd1c039ee712Pavel Maltsev private static IVehicle getVehicle() { 1691552204b9ebedb96dfb44c68ad519ef27c1d3c99Steven Moreland try { 17099e1a7555a9521c33203b68c5ab5bd1c039ee712Pavel Maltsev return android.hardware.automotive.vehicle.V2_0.IVehicle.getService(); 1711552204b9ebedb96dfb44c68ad519ef27c1d3c99Steven Moreland } catch (RemoteException e) { 172ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev Log.e(CarLog.TAG_SERVICE, "Failed to get IVehicle service", e); 173ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } catch (NoSuchElementException e) { 174ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev Log.e(CarLog.TAG_SERVICE, "IVehicle service not registered yet"); 175ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 176ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev return null; 177ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 178ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 179ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private class VehicleDeathRecipient implements DeathRecipient { 180ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private int deathCount = 0; 181ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 182ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev @Override 183ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev public void serviceDied(long cookie) { 184ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev Log.w(CarLog.TAG_SERVICE, "Vehicle HAL died."); 185ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 186ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev try { 187ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mVehicle.unlinkToDeath(this); 188ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } catch (RemoteException e) { 189ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev Log.e(CarLog.TAG_SERVICE, "Failed to unlinkToDeath", e); // Log and continue. 190ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 191ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mVehicle = null; 192ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 193ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mVhalCrashTracker.crashDetected(); 194ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 1952cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev Log.i(CarLog.TAG_SERVICE, "Trying to reconnect to Vehicle HAL: " + 1962cc76d0f8f401f1b62d019da3a9c097c9f52804cPavel Maltsev mVehicleInterfaceName); 19799e1a7555a9521c33203b68c5ab5bd1c039ee712Pavel Maltsev mVehicle = getVehicleWithTimeout(WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS); 198ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev if (mVehicle == null) { 199ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev throw new IllegalStateException("Failed to reconnect to Vehicle HAL"); 200ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 201ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 202ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev linkToDeath(mVehicle, this); 203ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 204ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev Log.i(CarLog.TAG_SERVICE, "Notifying car service Vehicle HAL reconnected..."); 205ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mICarImpl.vehicleHalReconnected(mVehicle); 206ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 207ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 208ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 209ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private static void linkToDeath(IVehicle vehicle, DeathRecipient recipient) { 210ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev try { 211ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev vehicle.linkToDeath(recipient, 0); 212ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } catch (RemoteException e) { 213ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev throw new IllegalStateException("Failed to linkToDeath Vehicle HAL"); 214ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 215ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 216ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 217ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev @VisibleForTesting 218ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev static class CrashTracker { 219ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private final int mMaxCrashCountLimit; 220ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private final int mSlidingWindowMillis; 221ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 222ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private final long[] mCrashTimestamps; 223ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private final RingBufferIndices mCrashTimestampsIndices; 224ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev private final Runnable mCallback; 225ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 226ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev /** 227ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev * If maxCrashCountLimit number of crashes occurred within slidingWindowMillis time 228ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev * frame then call provided callback function. 229ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev */ 230ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev CrashTracker(int maxCrashCountLimit, int slidingWindowMillis, Runnable callback) { 231ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mMaxCrashCountLimit = maxCrashCountLimit; 232ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mSlidingWindowMillis = slidingWindowMillis; 233ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCallback = callback; 234ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 235ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCrashTimestamps = new long[maxCrashCountLimit]; 236ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCrashTimestampsIndices = new RingBufferIndices(mMaxCrashCountLimit); 237ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 238ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 239ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev void crashDetected() { 240ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev long lastCrash = SystemClock.elapsedRealtime(); 241ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCrashTimestamps[mCrashTimestampsIndices.add()] = lastCrash; 242ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 243ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev if (mCrashTimestampsIndices.size() == mMaxCrashCountLimit) { 244ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev long firstCrash = mCrashTimestamps[mCrashTimestampsIndices.indexOf(0)]; 245ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev 246ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev if (lastCrash - firstCrash < mSlidingWindowMillis) { 247ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev mCallback.run(); 248ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 249ec83b63c47f65c5978eec3ee24952969a17b1ee7Pavel Maltsev } 2501552204b9ebedb96dfb44c68ad519ef27c1d3c99Steven Moreland } 2510d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev } 252920444970ec041d6b5c886f8d679cda5a3d91eb9Chris Phoenix} 253