blob: 07ae87941199ba8762842eb8d77f35f87e7e600c [file] [log] [blame]
Max Dashoukff9ffbc2021-02-16 11:36:39 -08001/*
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 */
16package com.android.car.telemetry;
17
Rui Qiu8c415de2021-05-03 15:52:16 -070018import static android.car.telemetry.CarTelemetryManager.ERROR_NEWER_MANIFEST_EXISTS;
Rui Qiu9bc1bb92021-04-08 15:41:48 -070019import static android.car.telemetry.CarTelemetryManager.ERROR_NONE;
Rui Qiu8c415de2021-05-03 15:52:16 -070020import static android.car.telemetry.CarTelemetryManager.ERROR_PARSE_MANIFEST_FAILED;
21import static android.car.telemetry.CarTelemetryManager.ERROR_SAME_MANIFEST_EXISTS;
Rui Qiu9bc1bb92021-04-08 15:41:48 -070022
Rui Qiuf6668202021-04-08 15:37:20 -070023import android.annotation.NonNull;
24import android.car.Car;
Rui Qiu9bc1bb92021-04-08 15:41:48 -070025import android.car.telemetry.CarTelemetryManager.AddManifestError;
Rui Qiuf6668202021-04-08 15:37:20 -070026import android.car.telemetry.ICarTelemetryService;
27import android.car.telemetry.ICarTelemetryServiceListener;
Rui Qiu9bc1bb92021-04-08 15:41:48 -070028import android.car.telemetry.ManifestKey;
Rui Qiuf6668202021-04-08 15:37:20 -070029import android.content.Context;
Rui Qiua3418982021-08-20 11:21:12 -070030import android.os.Handler;
31import android.os.HandlerThread;
Max Dashoukff9ffbc2021-02-16 11:36:39 -080032import android.util.IndentingPrintWriter;
Rui Qiuf6668202021-04-08 15:37:20 -070033import android.util.Slog;
Max Dashoukff9ffbc2021-02-16 11:36:39 -080034
Rui Qiua3418982021-08-20 11:21:12 -070035import com.android.car.CarLocalServices;
Max Dashoukff9ffbc2021-02-16 11:36:39 -080036import com.android.car.CarServiceBase;
Rui Qiua3418982021-08-20 11:21:12 -070037import com.android.car.CarServiceUtils;
38import com.android.car.systeminterface.SystemInterface;
Rui Qiuebfbcfb2021-05-18 17:01:27 -070039import com.android.internal.annotations.GuardedBy;
Max Dashoukff9ffbc2021-02-16 11:36:39 -080040
Rui Qiu8c415de2021-05-03 15:52:16 -070041import com.google.protobuf.InvalidProtocolBufferException;
42
Rui Qiua3418982021-08-20 11:21:12 -070043import java.io.File;
Rui Qiu8c415de2021-05-03 15:52:16 -070044import java.util.HashMap;
45import java.util.Map;
46
Max Dashoukff9ffbc2021-02-16 11:36:39 -080047/**
48 * CarTelemetryService manages OEM telemetry collection, processing and communication
49 * with a data upload service.
50 */
Rui Qiuf6668202021-04-08 15:37:20 -070051public class CarTelemetryService extends ICarTelemetryService.Stub implements CarServiceBase {
Max Dashoukff9ffbc2021-02-16 11:36:39 -080052
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -070053 // TODO(b/189340793): Rename Manifest to MetricsConfig
54
Rui Qiuf6668202021-04-08 15:37:20 -070055 private static final boolean DEBUG = false;
Rui Qiu8c415de2021-05-03 15:52:16 -070056 private static final int DEFAULT_VERSION = 0;
Rui Qiuf6668202021-04-08 15:37:20 -070057 private static final String TAG = CarTelemetryService.class.getSimpleName();
Rui Qiua3418982021-08-20 11:21:12 -070058 public static final String TELEMETRY_DIR = "telemetry";
Rui Qiuf6668202021-04-08 15:37:20 -070059
60 private final Context mContext;
Rui Qiua3418982021-08-20 11:21:12 -070061 private final File mRootDirectory;
62 private final HandlerThread mTelemetryThread = CarServiceUtils.getHandlerThread(
63 CarTelemetryService.class.getSimpleName());
64 private final Handler mTelemetryHandler = new Handler(mTelemetryThread.getLooper());
Rui Qiuebfbcfb2021-05-18 17:01:27 -070065 @GuardedBy("mLock")
Rui Qiu8c415de2021-05-03 15:52:16 -070066 private final Map<String, Integer> mNameVersionMap = new HashMap<>();
Rui Qiuebfbcfb2021-05-18 17:01:27 -070067 private final Object mLock = new Object();
Rui Qiuf6668202021-04-08 15:37:20 -070068
Rui Qiuebfbcfb2021-05-18 17:01:27 -070069 @GuardedBy("mLock")
Rui Qiuf6668202021-04-08 15:37:20 -070070 private ICarTelemetryServiceListener mListener;
Rui Qiua3418982021-08-20 11:21:12 -070071 private MetricsConfigStore mMetricsConfigStore;
Rui Qiuf6668202021-04-08 15:37:20 -070072
73 public CarTelemetryService(Context context) {
74 mContext = context;
Rui Qiua3418982021-08-20 11:21:12 -070075 SystemInterface systemInterface = CarLocalServices.getService(SystemInterface.class);
76 // full root directory path is /data/system/car/telemetry
77 mRootDirectory = new File(systemInterface.getSystemCarDir(), TELEMETRY_DIR);
Max Dashoukff9ffbc2021-02-16 11:36:39 -080078 }
79
80 @Override
81 public void init() {
Rui Qiua3418982021-08-20 11:21:12 -070082 mTelemetryHandler.post(() -> {
83 mMetricsConfigStore = new MetricsConfigStore(mRootDirectory);
84 mMetricsConfigStore.getActiveMetricsConfigs();
85 // TODO(b/197343030): mDataBroker.addMetricsConfig to start metrics collection
86 });
Max Dashoukff9ffbc2021-02-16 11:36:39 -080087 }
88
89 @Override
90 public void release() {
Rui Qiuf6668202021-04-08 15:37:20 -070091 // nothing to do
Max Dashoukff9ffbc2021-02-16 11:36:39 -080092 }
93
94 @Override
95 public void dump(IndentingPrintWriter writer) {
96 writer.println("Car Telemetry service");
97 }
Rui Qiuf6668202021-04-08 15:37:20 -070098
99 /**
100 * Registers a listener with CarTelemetryService for the service to send data to cloud app.
101 */
102 @Override
103 public void setListener(@NonNull ICarTelemetryServiceListener listener) {
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700104 // TODO(b/184890506): verify that only a hardcoded app can set the listener
Rui Qiuf6668202021-04-08 15:37:20 -0700105 mContext.enforceCallingOrSelfPermission(
106 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700107 synchronized (mLock) {
108 setListenerLocked(listener);
Rui Qiuf6668202021-04-08 15:37:20 -0700109 }
Rui Qiuf6668202021-04-08 15:37:20 -0700110 }
111
112 /**
113 * Clears the listener registered with CarTelemetryService.
114 */
115 @Override
116 public void clearListener() {
117 mContext.enforceCallingOrSelfPermission(
118 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700119 synchronized (mLock) {
120 clearListenerLocked();
Rui Qiuf6668202021-04-08 15:37:20 -0700121 }
Rui Qiuf6668202021-04-08 15:37:20 -0700122 }
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700123
124 /**
125 * Allows client to send telemetry manifests.
126 *
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700127 * @param key the unique key to identify the manifest.
128 * @param config the serialized bytes of a Manifest object.
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700129 * @return {@link AddManifestError} the error code.
130 */
131 @Override
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700132 public @AddManifestError int addManifest(@NonNull ManifestKey key, @NonNull byte[] config) {
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700133 mContext.enforceCallingOrSelfPermission(
134 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700135 synchronized (mLock) {
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700136 return addManifestLocked(key, config);
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700137 }
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700138 }
139
140 /**
141 * Removes a manifest based on the key.
142 */
143 @Override
144 public boolean removeManifest(@NonNull ManifestKey key) {
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700145 mContext.enforceCallingOrSelfPermission(
146 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700147 synchronized (mLock) {
148 return removeManifestLocked(key);
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700149 }
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700150 }
151
152 /**
153 * Removes all manifests.
154 */
155 @Override
156 public void removeAllManifests() {
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700157 mContext.enforceCallingOrSelfPermission(
158 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700159 synchronized (mLock) {
160 removeAllManifestsLocked();
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700161 }
162 }
163
164 /**
165 * Sends script results associated with the given key using the
166 * {@link ICarTelemetryServiceListener}.
167 */
168 @Override
169 public void sendFinishedReports(@NonNull ManifestKey key) {
170 // TODO(b/184087869): Implement
171 mContext.enforceCallingOrSelfPermission(
172 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
173 if (DEBUG) {
174 Slog.d(TAG, "Flushing reports for a manifest");
175 }
176 }
177
178 /**
179 * Sends all script results associated using the {@link ICarTelemetryServiceListener}.
180 */
181 @Override
182 public void sendAllFinishedReports() {
183 // TODO(b/184087869): Implement
184 mContext.enforceCallingOrSelfPermission(
185 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
186 if (DEBUG) {
187 Slog.d(TAG, "Flushing all reports");
188 }
189 }
190
191 /**
192 * Sends all errors using the {@link ICarTelemetryServiceListener}.
193 */
194 @Override
195 public void sendScriptExecutionErrors() {
196 // TODO(b/184087869): Implement
197 mContext.enforceCallingOrSelfPermission(
198 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
199 if (DEBUG) {
200 Slog.d(TAG, "Flushing script execution errors");
201 }
202 }
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700203
204 @GuardedBy("mLock")
205 private void setListenerLocked(@NonNull ICarTelemetryServiceListener listener) {
206 if (DEBUG) {
207 Slog.d(TAG, "Setting the listener for car telemetry service");
208 }
209 mListener = listener;
210 }
211
212 @GuardedBy("mLock")
213 private void clearListenerLocked() {
214 if (DEBUG) {
215 Slog.d(TAG, "Clearing listener");
216 }
217 mListener = null;
218 }
219
220 @GuardedBy("mLock")
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700221 private @AddManifestError int addManifestLocked(ManifestKey key, byte[] configProto) {
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700222 if (DEBUG) {
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700223 Slog.d(TAG, "Adding MetricsConfig to car telemetry service");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700224 }
225 int currentVersion = mNameVersionMap.getOrDefault(key.getName(), DEFAULT_VERSION);
226 if (currentVersion > key.getVersion()) {
227 return ERROR_NEWER_MANIFEST_EXISTS;
228 } else if (currentVersion == key.getVersion()) {
229 return ERROR_SAME_MANIFEST_EXISTS;
230 }
231
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700232 TelemetryProto.MetricsConfig metricsConfig;
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700233 try {
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700234 metricsConfig = TelemetryProto.MetricsConfig.parseFrom(configProto);
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700235 } catch (InvalidProtocolBufferException e) {
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700236 Slog.e(TAG, "Failed to parse MetricsConfig.", e);
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700237 return ERROR_PARSE_MANIFEST_FAILED;
238 }
239 mNameVersionMap.put(key.getName(), key.getVersion());
240
Zhomart Mukhamejanovee8c0de2021-05-20 11:42:19 -0700241 // TODO(b/186047142): Store the MetricsConfig to disk
242 // TODO(b/186047142): Send metricsConfig to a script manager or a queue
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700243 return ERROR_NONE;
244 }
245
246 @GuardedBy("mLock")
247 private boolean removeManifestLocked(@NonNull ManifestKey key) {
248 Integer version = mNameVersionMap.remove(key.getName());
249 if (version == null) {
250 return false;
251 }
252 // TODO(b/186047142): Delete manifest from disk and remove it from queue
253 return true;
254 }
255
256 @GuardedBy("mLock")
257 private void removeAllManifestsLocked() {
258 if (DEBUG) {
259 Slog.d(TAG, "Removing all manifest from car telemetry service");
260 }
261 mNameVersionMap.clear();
262 // TODO(b/186047142): Delete all manifests from disk & queue
263 }
Max Dashoukff9ffbc2021-02-16 11:36:39 -0800264}