blob: 0e34f902c7d611fd3e78084ac2edaca798870cf7 [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;
Max Dashoukff9ffbc2021-02-16 11:36:39 -080030import android.util.IndentingPrintWriter;
Rui Qiuf6668202021-04-08 15:37:20 -070031import android.util.Slog;
Max Dashoukff9ffbc2021-02-16 11:36:39 -080032
33import com.android.car.CarServiceBase;
Rui Qiuebfbcfb2021-05-18 17:01:27 -070034import com.android.internal.annotations.GuardedBy;
Max Dashoukff9ffbc2021-02-16 11:36:39 -080035
Rui Qiu8c415de2021-05-03 15:52:16 -070036import com.google.protobuf.InvalidProtocolBufferException;
37
38import java.util.HashMap;
39import java.util.Map;
40
Max Dashoukff9ffbc2021-02-16 11:36:39 -080041/**
42 * CarTelemetryService manages OEM telemetry collection, processing and communication
43 * with a data upload service.
44 */
Rui Qiuf6668202021-04-08 15:37:20 -070045public class CarTelemetryService extends ICarTelemetryService.Stub implements CarServiceBase {
Max Dashoukff9ffbc2021-02-16 11:36:39 -080046
Rui Qiuf6668202021-04-08 15:37:20 -070047 private static final boolean DEBUG = false;
Rui Qiu8c415de2021-05-03 15:52:16 -070048 private static final int DEFAULT_VERSION = 0;
Rui Qiuf6668202021-04-08 15:37:20 -070049 private static final String TAG = CarTelemetryService.class.getSimpleName();
50
51 private final Context mContext;
Rui Qiuebfbcfb2021-05-18 17:01:27 -070052 @GuardedBy("mLock")
Rui Qiu8c415de2021-05-03 15:52:16 -070053 private final Map<String, Integer> mNameVersionMap = new HashMap<>();
Rui Qiuebfbcfb2021-05-18 17:01:27 -070054 private final Object mLock = new Object();
Rui Qiuf6668202021-04-08 15:37:20 -070055
Rui Qiuebfbcfb2021-05-18 17:01:27 -070056 @GuardedBy("mLock")
Rui Qiuf6668202021-04-08 15:37:20 -070057 private ICarTelemetryServiceListener mListener;
58
59 public CarTelemetryService(Context context) {
60 mContext = context;
Max Dashoukff9ffbc2021-02-16 11:36:39 -080061 }
62
63 @Override
64 public void init() {
Rui Qiuf6668202021-04-08 15:37:20 -070065 // nothing to do
Max Dashoukff9ffbc2021-02-16 11:36:39 -080066 }
67
68 @Override
69 public void release() {
Rui Qiuf6668202021-04-08 15:37:20 -070070 // nothing to do
Max Dashoukff9ffbc2021-02-16 11:36:39 -080071 }
72
73 @Override
74 public void dump(IndentingPrintWriter writer) {
75 writer.println("Car Telemetry service");
76 }
Rui Qiuf6668202021-04-08 15:37:20 -070077
78 /**
79 * Registers a listener with CarTelemetryService for the service to send data to cloud app.
80 */
81 @Override
82 public void setListener(@NonNull ICarTelemetryServiceListener listener) {
Rui Qiu9bc1bb92021-04-08 15:41:48 -070083 // TODO(b/184890506): verify that only a hardcoded app can set the listener
Rui Qiuf6668202021-04-08 15:37:20 -070084 mContext.enforceCallingOrSelfPermission(
85 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -070086 synchronized (mLock) {
87 setListenerLocked(listener);
Rui Qiuf6668202021-04-08 15:37:20 -070088 }
Rui Qiuf6668202021-04-08 15:37:20 -070089 }
90
91 /**
92 * Clears the listener registered with CarTelemetryService.
93 */
94 @Override
95 public void clearListener() {
96 mContext.enforceCallingOrSelfPermission(
97 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -070098 synchronized (mLock) {
99 clearListenerLocked();
Rui Qiuf6668202021-04-08 15:37:20 -0700100 }
Rui Qiuf6668202021-04-08 15:37:20 -0700101 }
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700102
103 /**
104 * Allows client to send telemetry manifests.
105 *
106 * @param key the unique key to identify the manifest.
107 * @param manifest the serialized bytes of a Manifest object.
108 * @return {@link AddManifestError} the error code.
109 */
110 @Override
111 public @AddManifestError int addManifest(@NonNull ManifestKey key, @NonNull byte[] manifest) {
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700112 mContext.enforceCallingOrSelfPermission(
113 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700114 synchronized (mLock) {
115 return addManifestLocked(key, manifest);
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700116 }
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700117 }
118
119 /**
120 * Removes a manifest based on the key.
121 */
122 @Override
123 public boolean removeManifest(@NonNull ManifestKey key) {
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700124 mContext.enforceCallingOrSelfPermission(
125 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700126 synchronized (mLock) {
127 return removeManifestLocked(key);
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700128 }
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700129 }
130
131 /**
132 * Removes all manifests.
133 */
134 @Override
135 public void removeAllManifests() {
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700136 mContext.enforceCallingOrSelfPermission(
137 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700138 synchronized (mLock) {
139 removeAllManifestsLocked();
Rui Qiu9bc1bb92021-04-08 15:41:48 -0700140 }
141 }
142
143 /**
144 * Sends script results associated with the given key using the
145 * {@link ICarTelemetryServiceListener}.
146 */
147 @Override
148 public void sendFinishedReports(@NonNull ManifestKey key) {
149 // TODO(b/184087869): Implement
150 mContext.enforceCallingOrSelfPermission(
151 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
152 if (DEBUG) {
153 Slog.d(TAG, "Flushing reports for a manifest");
154 }
155 }
156
157 /**
158 * Sends all script results associated using the {@link ICarTelemetryServiceListener}.
159 */
160 @Override
161 public void sendAllFinishedReports() {
162 // TODO(b/184087869): Implement
163 mContext.enforceCallingOrSelfPermission(
164 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
165 if (DEBUG) {
166 Slog.d(TAG, "Flushing all reports");
167 }
168 }
169
170 /**
171 * Sends all errors using the {@link ICarTelemetryServiceListener}.
172 */
173 @Override
174 public void sendScriptExecutionErrors() {
175 // TODO(b/184087869): Implement
176 mContext.enforceCallingOrSelfPermission(
177 Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener");
178 if (DEBUG) {
179 Slog.d(TAG, "Flushing script execution errors");
180 }
181 }
Rui Qiuebfbcfb2021-05-18 17:01:27 -0700182
183 @GuardedBy("mLock")
184 private void setListenerLocked(@NonNull ICarTelemetryServiceListener listener) {
185 if (DEBUG) {
186 Slog.d(TAG, "Setting the listener for car telemetry service");
187 }
188 mListener = listener;
189 }
190
191 @GuardedBy("mLock")
192 private void clearListenerLocked() {
193 if (DEBUG) {
194 Slog.d(TAG, "Clearing listener");
195 }
196 mListener = null;
197 }
198
199 @GuardedBy("mLock")
200 private @AddManifestError int addManifestLocked(ManifestKey key, byte[] manifest) {
201 if (DEBUG) {
202 Slog.d(TAG, "Adding manifest to car telemetry service");
203 }
204 int currentVersion = mNameVersionMap.getOrDefault(key.getName(), DEFAULT_VERSION);
205 if (currentVersion > key.getVersion()) {
206 return ERROR_NEWER_MANIFEST_EXISTS;
207 } else if (currentVersion == key.getVersion()) {
208 return ERROR_SAME_MANIFEST_EXISTS;
209 }
210
211 TelemetryProto.Manifest parsedManifest;
212 try {
213 parsedManifest = TelemetryProto.Manifest.parseFrom(manifest);
214 } catch (InvalidProtocolBufferException e) {
215 Slog.e(TAG, "Failed to parse manifest.", e);
216 return ERROR_PARSE_MANIFEST_FAILED;
217 }
218 mNameVersionMap.put(key.getName(), key.getVersion());
219
220 // TODO(b/186047142): Store the manifest to disk
221 // TODO(b/186047142): Send parsedManifest to a script manager or a queue
222 return ERROR_NONE;
223 }
224
225 @GuardedBy("mLock")
226 private boolean removeManifestLocked(@NonNull ManifestKey key) {
227 Integer version = mNameVersionMap.remove(key.getName());
228 if (version == null) {
229 return false;
230 }
231 // TODO(b/186047142): Delete manifest from disk and remove it from queue
232 return true;
233 }
234
235 @GuardedBy("mLock")
236 private void removeAllManifestsLocked() {
237 if (DEBUG) {
238 Slog.d(TAG, "Removing all manifest from car telemetry service");
239 }
240 mNameVersionMap.clear();
241 // TODO(b/186047142): Delete all manifests from disk & queue
242 }
Max Dashoukff9ffbc2021-02-16 11:36:39 -0800243}