Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2021 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 | package com.android.car.telemetry; |
| 17 | |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 18 | import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_NONE; |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 19 | import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_PARSE_FAILED; |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 20 | import static android.car.telemetry.CarTelemetryManager.ERROR_METRICS_CONFIG_UNKNOWN; |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 21 | |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 22 | import android.annotation.NonNull; |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 23 | import android.app.StatsManager; |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 24 | import android.car.Car; |
| 25 | import android.car.telemetry.ICarTelemetryService; |
| 26 | import android.car.telemetry.ICarTelemetryServiceListener; |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 27 | import android.car.telemetry.MetricsConfigKey; |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 28 | import android.content.Context; |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 29 | import android.os.Handler; |
| 30 | import android.os.HandlerThread; |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 31 | import android.os.PersistableBundle; |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 32 | import android.os.RemoteException; |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 33 | import android.util.IndentingPrintWriter; |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 34 | import android.util.Slog; |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 35 | |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 36 | import com.android.car.CarLocalServices; |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 37 | import com.android.car.CarLog; |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 38 | import com.android.car.CarPropertyService; |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 39 | import com.android.car.CarServiceBase; |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 40 | import com.android.car.CarServiceUtils; |
| 41 | import com.android.car.systeminterface.SystemInterface; |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 42 | import com.android.car.telemetry.databroker.DataBroker; |
| 43 | import com.android.car.telemetry.databroker.DataBrokerController; |
| 44 | import com.android.car.telemetry.databroker.DataBrokerImpl; |
| 45 | import com.android.car.telemetry.publisher.PublisherFactory; |
| 46 | import com.android.car.telemetry.publisher.StatsManagerImpl; |
| 47 | import com.android.car.telemetry.publisher.StatsManagerProxy; |
| 48 | import com.android.car.telemetry.systemmonitor.SystemMonitor; |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 49 | import com.android.internal.annotations.VisibleForTesting; |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 50 | |
Rui Qiu | 8c415de | 2021-05-03 15:52:16 -0700 | [diff] [blame] | 51 | import com.google.protobuf.InvalidProtocolBufferException; |
| 52 | |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 53 | import java.io.ByteArrayOutputStream; |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 54 | import java.io.File; |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 55 | import java.io.IOException; |
Rui Qiu | 8c415de | 2021-05-03 15:52:16 -0700 | [diff] [blame] | 56 | |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 57 | /** |
| 58 | * CarTelemetryService manages OEM telemetry collection, processing and communication |
| 59 | * with a data upload service. |
| 60 | */ |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 61 | public class CarTelemetryService extends ICarTelemetryService.Stub implements CarServiceBase { |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 62 | |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 63 | private static final boolean DEBUG = false; |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 64 | public static final String TELEMETRY_DIR = "telemetry"; |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 65 | |
| 66 | private final Context mContext; |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 67 | private final CarPropertyService mCarPropertyService; |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 68 | private final HandlerThread mTelemetryThread = CarServiceUtils.getHandlerThread( |
| 69 | CarTelemetryService.class.getSimpleName()); |
| 70 | private final Handler mTelemetryHandler = new Handler(mTelemetryThread.getLooper()); |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 71 | |
| 72 | private ICarTelemetryServiceListener mListener; |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 73 | private DataBroker mDataBroker; |
| 74 | private DataBrokerController mDataBrokerController; |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 75 | private MetricsConfigStore mMetricsConfigStore; |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 76 | private PublisherFactory mPublisherFactory; |
| 77 | private ResultStore mResultStore; |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 78 | private StatsManagerProxy mStatsManagerProxy; |
| 79 | private SystemMonitor mSystemMonitor; |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 80 | |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 81 | public CarTelemetryService(Context context, CarPropertyService carPropertyService) { |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 82 | mContext = context; |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 83 | mCarPropertyService = carPropertyService; |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | @Override |
| 87 | public void init() { |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 88 | mTelemetryHandler.post(() -> { |
Rui Qiu | 3d3806b | 2021-09-22 11:42:45 -0700 | [diff] [blame] | 89 | SystemInterface systemInterface = CarLocalServices.getService(SystemInterface.class); |
| 90 | // full root directory path is /data/system/car/telemetry |
| 91 | File rootDirectory = new File(systemInterface.getSystemCarDir(), TELEMETRY_DIR); |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 92 | // initialize all necessary components |
Rui Qiu | 3d3806b | 2021-09-22 11:42:45 -0700 | [diff] [blame] | 93 | mMetricsConfigStore = new MetricsConfigStore(rootDirectory); |
| 94 | mResultStore = new ResultStore(rootDirectory); |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 95 | mStatsManagerProxy = new StatsManagerImpl( |
| 96 | mContext.getSystemService(StatsManager.class)); |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 97 | mPublisherFactory = new PublisherFactory(mCarPropertyService, mTelemetryHandler, |
Rui Qiu | 3d3806b | 2021-09-22 11:42:45 -0700 | [diff] [blame] | 98 | mStatsManagerProxy, rootDirectory); |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 99 | mDataBroker = new DataBrokerImpl(mContext, mPublisherFactory, mResultStore); |
| 100 | mSystemMonitor = SystemMonitor.create(mContext, mTelemetryHandler); |
Rui Qiu | 3d3806b | 2021-09-22 11:42:45 -0700 | [diff] [blame] | 101 | // controller starts metrics collection after boot complete |
| 102 | mDataBrokerController = new DataBrokerController(mDataBroker, mTelemetryHandler, |
| 103 | mMetricsConfigStore, mSystemMonitor, |
| 104 | systemInterface.getSystemStateInterface()); |
Rui Qiu | a341898 | 2021-08-20 11:21:12 -0700 | [diff] [blame] | 105 | }); |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | @Override |
| 109 | public void release() { |
Rui Qiu | ac8b5ba | 2021-08-25 16:04:17 -0700 | [diff] [blame] | 110 | // TODO(b/197969149): prevent threading issue, block main thread |
| 111 | mTelemetryHandler.post(() -> mResultStore.flushToDisk()); |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | @Override |
| 115 | public void dump(IndentingPrintWriter writer) { |
| 116 | writer.println("Car Telemetry service"); |
| 117 | } |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 118 | |
| 119 | /** |
| 120 | * Registers a listener with CarTelemetryService for the service to send data to cloud app. |
| 121 | */ |
| 122 | @Override |
| 123 | public void setListener(@NonNull ICarTelemetryServiceListener listener) { |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 124 | // TODO(b/184890506): verify that only a hardcoded app can set the listener |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 125 | mContext.enforceCallingOrSelfPermission( |
| 126 | Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener"); |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 127 | mTelemetryHandler.post(() -> { |
| 128 | if (DEBUG) { |
| 129 | Slog.d(CarLog.TAG_TELEMETRY, "Setting the listener for car telemetry service"); |
| 130 | } |
| 131 | mListener = listener; |
| 132 | }); |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 133 | } |
| 134 | |
| 135 | /** |
| 136 | * Clears the listener registered with CarTelemetryService. |
| 137 | */ |
| 138 | @Override |
| 139 | public void clearListener() { |
| 140 | mContext.enforceCallingOrSelfPermission( |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 141 | Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "clearListener"); |
| 142 | mTelemetryHandler.post(() -> { |
| 143 | if (DEBUG) { |
| 144 | Slog.d(CarLog.TAG_TELEMETRY, "Clearing the listener for car telemetry service"); |
| 145 | } |
| 146 | mListener = null; |
| 147 | }); |
Rui Qiu | f666820 | 2021-04-08 15:37:20 -0700 | [diff] [blame] | 148 | } |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 149 | |
| 150 | /** |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 151 | * Send a telemetry metrics config to the service. This method assumes |
| 152 | * {@link #setListener(ICarTelemetryServiceListener)} is called. Otherwise it does nothing. |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 153 | * |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 154 | * @param key the unique key to identify the MetricsConfig. |
| 155 | * @param config the serialized bytes of a MetricsConfig object. |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 156 | */ |
| 157 | @Override |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 158 | public void addMetricsConfig(@NonNull MetricsConfigKey key, @NonNull byte[] config) { |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 159 | mContext.enforceCallingOrSelfPermission( |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 160 | Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "addMetricsConfig"); |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 161 | mTelemetryHandler.post(() -> { |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 162 | if (mListener == null) { |
| 163 | Slog.w(CarLog.TAG_TELEMETRY, "ICarTelemetryServiceListener is not set"); |
| 164 | return; |
| 165 | } |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 166 | Slog.d(CarLog.TAG_TELEMETRY, "Adding metrics config " + key.getName() |
| 167 | + " to car telemetry service"); |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 168 | TelemetryProto.MetricsConfig metricsConfig = null; |
| 169 | int status = ERROR_METRICS_CONFIG_UNKNOWN; |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 170 | try { |
| 171 | metricsConfig = TelemetryProto.MetricsConfig.parseFrom(config); |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 172 | } catch (InvalidProtocolBufferException e) { |
| 173 | Slog.e(CarLog.TAG_TELEMETRY, "Failed to parse MetricsConfig.", e); |
| 174 | status = ERROR_METRICS_CONFIG_PARSE_FAILED; |
| 175 | } |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 176 | // if config can be parsed, add it to persistent storage |
| 177 | if (metricsConfig != null) { |
| 178 | status = mMetricsConfigStore.addMetricsConfig(metricsConfig); |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 179 | // TODO(b/199410900): update logic once metrics configs have expiration dates |
| 180 | mDataBroker.addMetricsConfiguration(metricsConfig); |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 181 | } |
| 182 | // If no error (a config is successfully added), script results from an older version |
| 183 | // should be deleted |
| 184 | if (status == ERROR_METRICS_CONFIG_NONE) { |
Rui Qiu | 9f80c7c | 2021-09-28 15:15:36 -0700 | [diff] [blame] | 185 | mResultStore.removeResult(key.getName()); |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 186 | } |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 187 | try { |
| 188 | mListener.onAddMetricsConfigStatus(key, status); |
| 189 | } catch (RemoteException e) { |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 190 | Slog.w(CarLog.TAG_TELEMETRY, "error with ICarTelemetryServiceListener", e); |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 191 | } |
| 192 | }); |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 193 | } |
| 194 | |
| 195 | /** |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 196 | * Removes a metrics config based on the key. This will also remove outputs produced by the |
Rui Qiu | 9f80c7c | 2021-09-28 15:15:36 -0700 | [diff] [blame] | 197 | * MetricsConfig. |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 198 | * |
| 199 | * @param key the unique identifier of a MetricsConfig. |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 200 | */ |
| 201 | @Override |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 202 | public void removeMetricsConfig(@NonNull MetricsConfigKey key) { |
Rui Qiu | 9f80c7c | 2021-09-28 15:15:36 -0700 | [diff] [blame] | 203 | mContext.enforceCallingOrSelfPermission( |
| 204 | Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "removeMetricsConfig"); |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 205 | mTelemetryHandler.post(() -> { |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 206 | Slog.d(CarLog.TAG_TELEMETRY, "Removing metrics config " + key.getName() |
| 207 | + " from car telemetry service"); |
Rui Qiu | 9f80c7c | 2021-09-28 15:15:36 -0700 | [diff] [blame] | 208 | // TODO(b/198792767): Check both config name and config version for removal |
| 209 | mDataBroker.removeMetricsConfiguration(key.getName()); |
| 210 | mResultStore.removeResult(key.getName()); |
| 211 | mMetricsConfigStore.removeMetricsConfig(key.getName()); |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 212 | }); |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | /** |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 216 | * Removes all MetricsConfigs. This will also remove all MetricsConfig outputs. |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 217 | */ |
| 218 | @Override |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 219 | public void removeAllMetricsConfigs() { |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 220 | mContext.enforceCallingOrSelfPermission( |
Rui Qiu | 9f80c7c | 2021-09-28 15:15:36 -0700 | [diff] [blame] | 221 | Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "removeAllMetricsConfigs"); |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 222 | mTelemetryHandler.post(() -> { |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 223 | Slog.d(CarLog.TAG_TELEMETRY, |
| 224 | "Removing all metrics config from car telemetry service"); |
Rui Qiu | 9f80c7c | 2021-09-28 15:15:36 -0700 | [diff] [blame] | 225 | mDataBroker.removeAllMetricsConfigurations(); |
| 226 | mMetricsConfigStore.removeAllMetricsConfigs(); |
| 227 | mResultStore.removeAllResults(); |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 228 | }); |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 229 | } |
| 230 | |
| 231 | /** |
| 232 | * Sends script results associated with the given key using the |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 233 | * {@link ICarTelemetryServiceListener}. This method assumes listener is set. Otherwise it |
| 234 | * does nothing. |
| 235 | * |
| 236 | * @param key the unique identifier of a MetricsConfig. |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 237 | */ |
| 238 | @Override |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 239 | public void sendFinishedReports(@NonNull MetricsConfigKey key) { |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 240 | mContext.enforceCallingOrSelfPermission( |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 241 | Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "sendFinishedReports"); |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 242 | mTelemetryHandler.post(() -> { |
| 243 | if (mListener == null) { |
| 244 | Slog.w(CarLog.TAG_TELEMETRY, "ICarTelemetryServiceListener is not set"); |
| 245 | return; |
| 246 | } |
| 247 | if (DEBUG) { |
| 248 | Slog.d(CarLog.TAG_TELEMETRY, |
| 249 | "Flushing reports for metrics config " + key.getName()); |
| 250 | } |
| 251 | PersistableBundle result = mResultStore.getFinalResult(key.getName(), true); |
| 252 | TelemetryProto.TelemetryError error = mResultStore.getError(key.getName(), true); |
| 253 | if (result != null) { |
| 254 | sendFinalResult(key, result); |
| 255 | } else if (error != null) { |
| 256 | sendError(key, error); |
| 257 | } else { |
| 258 | Slog.w(CarLog.TAG_TELEMETRY, "config " + key.getName() |
| 259 | + " did not produce any results"); |
| 260 | } |
| 261 | }); |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | /** |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 265 | * Sends all script results or errors using the {@link ICarTelemetryServiceListener}. |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 266 | */ |
| 267 | @Override |
| 268 | public void sendAllFinishedReports() { |
| 269 | // TODO(b/184087869): Implement |
| 270 | mContext.enforceCallingOrSelfPermission( |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 271 | Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "sendAllFinishedReports"); |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 272 | if (DEBUG) { |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 273 | Slog.d(CarLog.TAG_TELEMETRY, "Flushing all reports"); |
Rui Qiu | 9bc1bb9 | 2021-04-08 15:41:48 -0700 | [diff] [blame] | 274 | } |
| 275 | } |
| 276 | |
Rui Qiu | d5b4b0b | 2021-09-14 15:51:50 -0700 | [diff] [blame] | 277 | private void sendFinalResult(MetricsConfigKey key, PersistableBundle result) { |
| 278 | try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { |
| 279 | result.writeToStream(bos); |
| 280 | mListener.onResult(key, bos.toByteArray()); |
| 281 | } catch (RemoteException e) { |
| 282 | Slog.w(CarLog.TAG_TELEMETRY, "error with ICarTelemetryServiceListener", e); |
| 283 | } catch (IOException e) { |
| 284 | Slog.w(CarLog.TAG_TELEMETRY, "failed to write bundle to output stream", e); |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | private void sendError(MetricsConfigKey key, TelemetryProto.TelemetryError error) { |
| 289 | try { |
| 290 | mListener.onError(key, error.toByteArray()); |
| 291 | } catch (RemoteException e) { |
| 292 | Slog.w(CarLog.TAG_TELEMETRY, "error with ICarTelemetryServiceListener", e); |
| 293 | } |
| 294 | } |
| 295 | |
Rui Qiu | 9b9341c | 2021-08-25 10:39:04 -0700 | [diff] [blame] | 296 | @VisibleForTesting |
| 297 | Handler getTelemetryHandler() { |
| 298 | return mTelemetryHandler; |
Rui Qiu | ebfbcfb | 2021-05-18 17:01:27 -0700 | [diff] [blame] | 299 | } |
Rui Qiu | f721b13 | 2021-09-10 12:41:09 -0700 | [diff] [blame] | 300 | |
| 301 | @VisibleForTesting |
| 302 | ResultStore getResultStore() { |
| 303 | return mResultStore; |
| 304 | } |
| 305 | |
| 306 | @VisibleForTesting |
| 307 | MetricsConfigStore getMetricsConfigStore() { |
| 308 | return mMetricsConfigStore; |
| 309 | } |
Max Dashouk | ff9ffbc | 2021-02-16 11:36:39 -0800 | [diff] [blame] | 310 | } |