diff options
author | Zhomart Mukhamejanov <zhomart@google.com> | 2021-05-20 11:42:19 -0700 |
---|---|---|
committer | Zhomart Mukhamejanov <zhomart@google.com> | 2021-05-26 12:28:04 -0700 |
commit | ee8c0de97db03e775f7654c3445a125dd18e7db1 (patch) | |
tree | f2894f9e8fcdba3f118cc9efaaa587509f285e04 | |
parent | 920ed595ce21c05384e189ef3fc407418da5cbf4 (diff) | |
download | Car-ee8c0de97db03e775f7654c3445a125dd18e7db1.tar.gz |
Change the format of the Manifest.
- Delete LogcatReader, we will add Publishers later.
- Rename CarTelemetryService Manifest proto usage,
this component will be updated later again
when Controller, Broker components are added.
Test: m -j CarService
Bug: 187525360
Change-Id: I1be7badf90a76a47ee2f4a4dc90ea9395dfe6e51
6 files changed, 61 insertions, 753 deletions
diff --git a/.clang-format b/.clang-format index 30e9edabbf..b652e192de 100644 --- a/.clang-format +++ b/.clang-format @@ -36,3 +36,7 @@ IncludeCategories: - Regex: '^".*' Priority: 1 --- +Language: Proto +BasedOnStyle: Google +ColumnLimit: 100 +--- diff --git a/service/src/com/android/car/telemetry/CarTelemetryService.java b/service/src/com/android/car/telemetry/CarTelemetryService.java index 0e34f902c7..695e25e772 100644 --- a/service/src/com/android/car/telemetry/CarTelemetryService.java +++ b/service/src/com/android/car/telemetry/CarTelemetryService.java @@ -44,6 +44,8 @@ import java.util.Map; */ public class CarTelemetryService extends ICarTelemetryService.Stub implements CarServiceBase { + // TODO(b/189340793): Rename Manifest to MetricsConfig + private static final boolean DEBUG = false; private static final int DEFAULT_VERSION = 0; private static final String TAG = CarTelemetryService.class.getSimpleName(); @@ -103,16 +105,16 @@ public class CarTelemetryService extends ICarTelemetryService.Stub implements Ca /** * Allows client to send telemetry manifests. * - * @param key the unique key to identify the manifest. - * @param manifest the serialized bytes of a Manifest object. + * @param key the unique key to identify the manifest. + * @param config the serialized bytes of a Manifest object. * @return {@link AddManifestError} the error code. */ @Override - public @AddManifestError int addManifest(@NonNull ManifestKey key, @NonNull byte[] manifest) { + public @AddManifestError int addManifest(@NonNull ManifestKey key, @NonNull byte[] config) { mContext.enforceCallingOrSelfPermission( Car.PERMISSION_USE_CAR_TELEMETRY_SERVICE, "setListener"); synchronized (mLock) { - return addManifestLocked(key, manifest); + return addManifestLocked(key, config); } } @@ -197,9 +199,9 @@ public class CarTelemetryService extends ICarTelemetryService.Stub implements Ca } @GuardedBy("mLock") - private @AddManifestError int addManifestLocked(ManifestKey key, byte[] manifest) { + private @AddManifestError int addManifestLocked(ManifestKey key, byte[] configProto) { if (DEBUG) { - Slog.d(TAG, "Adding manifest to car telemetry service"); + Slog.d(TAG, "Adding MetricsConfig to car telemetry service"); } int currentVersion = mNameVersionMap.getOrDefault(key.getName(), DEFAULT_VERSION); if (currentVersion > key.getVersion()) { @@ -208,17 +210,17 @@ public class CarTelemetryService extends ICarTelemetryService.Stub implements Ca return ERROR_SAME_MANIFEST_EXISTS; } - TelemetryProto.Manifest parsedManifest; + TelemetryProto.MetricsConfig metricsConfig; try { - parsedManifest = TelemetryProto.Manifest.parseFrom(manifest); + metricsConfig = TelemetryProto.MetricsConfig.parseFrom(configProto); } catch (InvalidProtocolBufferException e) { - Slog.e(TAG, "Failed to parse manifest.", e); + Slog.e(TAG, "Failed to parse MetricsConfig.", e); return ERROR_PARSE_MANIFEST_FAILED; } mNameVersionMap.put(key.getName(), key.getVersion()); - // TODO(b/186047142): Store the manifest to disk - // TODO(b/186047142): Send parsedManifest to a script manager or a queue + // TODO(b/186047142): Store the MetricsConfig to disk + // TODO(b/186047142): Send metricsConfig to a script manager or a queue return ERROR_NONE; } diff --git a/service/src/com/android/car/telemetry/LogFilter.java b/service/src/com/android/car/telemetry/LogFilter.java deleted file mode 100644 index 8f72fe84cf..0000000000 --- a/service/src/com/android/car/telemetry/LogFilter.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.car.telemetry; - -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import android.annotation.IntDef; -import android.util.Log; - -import com.android.car.telemetry.TelemetryProto.LogListener; -import com.android.car.telemetry.TelemetryProto.Manifest; - -import java.lang.annotation.Retention; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Encapsulates a filter that can be matched on log entries. Contains builder function to create - * list of LogFilter given the loglistener. - */ -public final class LogFilter { - - private static final String TAG = LogFilter.class.getSimpleName(); - - /** - * Types of filters to match against the logs. Different filter types will match in different - * ways. - */ - @Retention(SOURCE) - @IntDef({FILTER_TAG, SUBSTRING}) - @interface FilterType {} - static final int FILTER_TAG = 0; - static final int SUBSTRING = 1; - - private final int mLogListenerIndex; - private final @FilterType int mFilterType; - private final String mFilter; - - LogFilter(int logListenerIndex, @FilterType int filterType, String filter) { - this.mLogListenerIndex = logListenerIndex; - this.mFilterType = filterType; - if (filter == null) { - throw new NullPointerException("Null filter"); - } - this.mFilter = filter; - } - - int getLogListenerIndex() { - return mLogListenerIndex; - } - - @LogFilter.FilterType int getFilterType() { - return mFilterType; - } - - String getFilter() { - return mFilter; - } - - /** - * Creates a LogFilter instance. - * - * @param logListenerIndex the index of the logListener associated with the filter. - * @param filterType the type of filter. - * @param filter the value of the filter. - * @return created LogFilter instance. - */ - static LogFilter create(int logListenerIndex, @FilterType int filterType, String filter) { - return new LogFilter(logListenerIndex, filterType, filter); - } - - /** - * Builds a List of {@link LogFilter} instances from {@link Manifest} and the logListener name. - * - * @param manifest {@link Manifest} file that contains list of logListeners. - * @param logListenerName the name of the logListener as registered in the {@link Manifest}. - * @return List of {@link LogFilter} instances. - */ - static List<LogFilter> buildFilters(Manifest manifest, String logListenerName) { - int logListenerIndex = getLogListenerIndexFromName(manifest, logListenerName); - if (logListenerIndex == -1) { - Log.w(TAG, "log listener with name " + logListenerName - + " does not exist in manifest."); - return Collections.unmodifiableList(new ArrayList<>()); - } - - List<LogFilter> result = new ArrayList<>(); - result.addAll( - manifest.getLogListeners(logListenerIndex).getTagsList().stream() - .map(tag -> LogFilter.create(logListenerIndex, FILTER_TAG, tag)) - .collect(Collectors.toList())); - result.addAll( - manifest.getLogListeners(logListenerIndex).getTypesList().stream() - .map(LogFilter::typeToFilter) - .filter(Optional::isPresent) - .map(filter -> - LogFilter.create(logListenerIndex, SUBSTRING, filter.get())) - .collect(Collectors.toList())); - return Collections.unmodifiableList(result); - } - - /** - * Gets the index of the {@link LogListener} in the manifest's list of logListeners. - * Returns -1 if not found. - * - * @param manifest the {@link Manifest} that contains the definitions of the logListeners. - * @param logListenerName name of the {@link LogListener} to get index for. - * @return index of the logListener, -1 if not found. - */ - static int getLogListenerIndexFromName(Manifest manifest, String logListenerName) { - for (int i = 0; i < manifest.getLogListenersCount(); i++) { - LogListener listener = manifest.getLogListeners(i); - if (listener.getName().equals(logListenerName)) { - return i; - } - } - return -1; - } - - /** - * Converts log message filter {@link LogListener.Type} to corresponding filter string. - * - * @param type the filter {@link LogListener.Type}. - * @return the corresponding filter string for the logListener type. - */ - private static Optional<String> typeToFilter(LogListener.Type type) { - switch (type) { - case TYPE_UNSPECIFIED: - return Optional.empty(); - case EXCEPTIONS: - return Optional.of("Exception: "); - } - return Optional.empty(); - } - - /** - * Matches in different ways against {@link LogcatReader.LogEntry} components depending on - * filterType. - * - * @param entry the {@link LogcatReader.LogEntry} whose components will be matched against the - * filters. - * @return boolean denoting whether the filter can match the {@link LogcatReader.LogEntry}. - */ - boolean matches(LogcatReader.LogEntry entry) { - switch (getFilterType()) { - case FILTER_TAG: - return entry.mTag.equals(getFilter()); - case SUBSTRING: - return entry.mMessage.contains(getFilter()); - } - return false; - } - - @Override - public String toString() { - return "LogFilter{" - + "mLogListenerIndex=" + mLogListenerIndex + ", " - + "mFilterType=" + mFilterType + ", " - + "mFilter=" + mFilter - + "}"; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof LogFilter) { - LogFilter that = (LogFilter) o; - return this.mLogListenerIndex == that.getLogListenerIndex() - && this.mFilterType == that.getFilterType() - && this.mFilter.equals(that.getFilter()); - } - return false; - } - - @Override - public int hashCode() { - int hash = 1; - hash *= 1000003; - hash ^= mLogListenerIndex; - hash *= 1000003; - hash ^= Integer.hashCode(mFilterType); - hash *= 1000003; - hash ^= mFilter.hashCode(); - return hash; - } -} - diff --git a/service/src/com/android/car/telemetry/LogcatReader.java b/service/src/com/android/car/telemetry/LogcatReader.java deleted file mode 100644 index a83a72e412..0000000000 --- a/service/src/com/android/car/telemetry/LogcatReader.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.car.telemetry; - -import android.annotation.Nullable; -import android.net.LocalSocket; -import android.net.LocalSocketAddress; -import android.os.Bundle; -import android.os.Process; -import android.util.Log; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.ObjIntConsumer; -import java.util.function.Supplier; - -/** - * Reads Android logs while there are log listeners registered to it and sends the event through the - * mLogEventConsumer. - */ -public class LogcatReader { - private static final String TAG = LogcatReader.class.getSimpleName(); - - // TODO(b/180515554). Find a proper place for LOG_* constants. - // They will be used in ScriptExecutor as well. - /** The value of key to retrieve log seconds since epoch time from bundle. */ - private static final String LOG_SEC_KEY = "log.sec"; - - /** The value of key to retrieve log nanoseconds from bundle. */ - private static final String LOG_NSEC_KEY = "log.nsec"; - - /** The value of key to retrieve log tag from bundle. */ - private static final String LOG_TAG_KEY = "log.tag"; - - /** The value of key to retrieve log message from bundle. */ - private static final String LOG_MESSAGE_KEY = "log.message"; - - // Defined in system/core/liblog/include/log/log_read.h - private static final int LOGGER_ENTRY_MAX_LEN = 5 * 1024; - - // The entry sizes differ in Android 10. See - // https://cs.android.com/android/platform/superproject/+/android-10.0.0_r30:system/core/liblog/include/log/log_read.h - public static final int ENTRY_V1_SIZE = 20; - public static final int ENTRY_V2_V3_SIZE = 24; - public static final int ENTRY_V4_SIZE = 28; - - private final AtomicBoolean mRunning = new AtomicBoolean(false); - - private final ObjIntConsumer<Bundle> mLogEventConsumer; - private final Supplier<LocalSocket> mLocalSocketSupplier; - private final Executor mExecutor; - - private final HashSet<LogFilter> mLogFilters = new HashSet<>(); - - private synchronized boolean logFiltersEmpty() { - return mLogFilters.isEmpty(); - } - - /** - * Replicates {@code struct log_msg} from system/core/liblog/include/log/log_read.h and {@code - * struct AndroidLogEntry} from system/core/liblog/include/log/logprint.h. - */ - static class LogEntry { - long mTvSec; // seconds since Epoch - long mTvNSec; // nanoseconds - int mPid; // generating process's pid - long mTid; // generating process's tid - long mUid; // generating process's uid - int mPriority; // log priority, e.g. {@link Log#INFO}. - String mTag; - String mMessage; - - /** - * Parses raw bytes received from {@code logd}. - * - * @param data raw bytes - * @param readSize number of bytes received from logd. - */ - @Nullable - static LogEntry parse(byte[] data, int readSize) { - // Parsing log_msg struct defined in system/core/liblog/include/log/log_read.h. - // Only first headerSize is used to create LogEntry. Following message messageSize bytes - // define log message. - ByteBuffer dataBytes = ByteBuffer.wrap(data); - dataBytes.order(ByteOrder.LITTLE_ENDIAN); - int messageSize = dataBytes.getShort(); - int headerSize = dataBytes.getShort(); - if (readSize < messageSize + headerSize) { - Log.w( - TAG, "Invalid log message size " - + (messageSize + headerSize) - + ", received only " - + readSize); - return null; - } - LogEntry entry = new LogEntry(); - entry.mPid = dataBytes.getInt(); - entry.mTid = dataBytes.getInt(); - entry.mTvSec = dataBytes.getInt(); - entry.mTvNSec = dataBytes.getInt(); - if (headerSize >= ENTRY_V2_V3_SIZE) { - dataBytes.position(dataBytes.position() + 4); // lid is not used here. - } - if (headerSize >= ENTRY_V4_SIZE) { - entry.mUid = dataBytes.getInt(); - } - - // Parsing log message. - // See android_log_processLogBuffer() in system/core/liblog/logprint.cpp for details. - // message format: <priority:1><tag:N>\0<message:N>\0 - // TODO(b/180516393): improve message parsing that were not transferred - // from the cpp above. Also verify this mechanism is ok from selinux perspective. - - if (messageSize < 3) { - Log.w(TAG, "Log message is too small, size=" + messageSize); - return null; - } - if (headerSize != dataBytes.position()) { - Log.w(TAG, "Invalid header size " + headerSize + ", expected " - + dataBytes.position()); - return null; - } - int msgStart = -1; - int msgEnd = -1; - for (int i = 1; i < messageSize; i++) { - if (data[headerSize + i] == 0) { - if (msgStart == -1) { - msgStart = i + 1 + headerSize; - } else { - msgEnd = i + headerSize; - break; - } - } - } - if (msgStart == -1) { - Log.w(TAG, "Invalid log message"); - return null; - } - if (msgEnd == -1) { - msgEnd = Math.max(msgStart, messageSize - 1); - } - entry.mPriority = data[headerSize]; - entry.mTag = - new String(data, headerSize + 1, msgStart - headerSize - 2, - StandardCharsets.US_ASCII); - entry.mMessage = - new String(data, msgStart, msgEnd - msgStart, StandardCharsets.US_ASCII); - return entry; - } - } - - /** - * Constructs {@link LogcatReader}. - * - * @param logEventConsumer a consumer that's called when a filter matches a log. - * @param localSocketSupplier a supplier for LocalSocket to connect logd. - * @param executor an {@link Executor} to run the LogcatReader instance. - */ - public LogcatReader( - ObjIntConsumer<Bundle> logEventConsumer, - Supplier<LocalSocket> localSocketSupplier, - Executor executor) { - this.mLogEventConsumer = logEventConsumer; - this.mLocalSocketSupplier = localSocketSupplier; - this.mExecutor = executor; - } - - /** Runs {@link LogcatReader}. */ - private void run() { - Log.d(TAG, "Running LogcatReader"); - - // Under the hood, logcat receives logs from logd, to remove the middleman, LogcatReader - // doesn't run logcat, but directly connects to logd socket and parses raw logs. - try (LocalSocket socket = mLocalSocketSupplier.get()) { - // Connect to /dev/socket/logdr - socket.connect(new LocalSocketAddress("logdr", LocalSocketAddress.Namespace.RESERVED)); - try (OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream()); - InputStream reader = socket.getInputStream()) { - // Ask for streaming log and set tail=1 to get only new logs. - // See system/core/liblog/logd_reader.cpp for example on how to interact with logdr. - writer.write("stream tail=1"); - writer.flush(); - Log.d(TAG, "Sent request to logd and awaiting for logs"); - - byte[] data = new byte[LOGGER_ENTRY_MAX_LEN + 1]; - while (!logFiltersEmpty()) { - int n = reader.read(data, 0, LOGGER_ENTRY_MAX_LEN); - if (n == -1) { - Log.e(TAG, "Disconnected from logd"); - return; - } - LogEntry entry = LogEntry.parse(data, n); - if (entry == null) { - continue; - } - - // Ignore the logs from the telemetry service. This - // makes sure a recursive log storm does not happen - i.e. app produces a log - // which in turn executes a code path that produces another log. - if (entry.mUid == Process.myUid()) { - continue; - } - // Check if it's running before processing the logs, because by the time we get - // here ScriptExecutor might get disconnected. - if (!mRunning.get()) { - Log.d(TAG, "Not running anymore, exiting."); - return; - } - // Keep track of which logListener an event for this entry has been sent, - // so that the same entry isn't sent multiple times for the same logListener - // if its multiple filters match. - HashSet<Integer> sentLogListenerIndices = new HashSet<>(); - for (LogFilter filter : mLogFilters) { - if (!sentLogListenerIndices.contains(filter.getLogListenerIndex()) - && filter.matches(entry)) { - sentLogListenerIndices.add(filter.getLogListenerIndex()); - sendLogEvent(filter.getLogListenerIndex(), entry); - } - } - } - Log.d(TAG, "Log filters are empty, exiting."); - } - } catch (IOException e) { - Log.e(TAG, "Failed to connect to logd", e); - } finally { - mRunning.set(false); - } - } - - /** - * Sends the log event to the through the mLogEventConsumer. - * - * @param logListenerIndex the index of the logListener, whose function will receive the log - * event. - * @param entry the LogEntry instance to be bundled up and sent as event. - */ - private void sendLogEvent(int logListenerIndex, LogEntry entry) { - Bundle event = new Bundle(); - event.putLong(LOG_SEC_KEY, entry.mTvSec); - event.putLong(LOG_NSEC_KEY, entry.mTvNSec); - event.putString(LOG_TAG_KEY, entry.mTag); - event.putString(LOG_MESSAGE_KEY, entry.mMessage); - mLogEventConsumer.accept(event, logListenerIndex); - } - - /** - * Subscribes the list of {@link LogFilter} instances. - * - * @param newLogFilters the list of new log filters to be added to mLogFilters. - */ - synchronized void subscribeLogFilters(List<LogFilter> newLogFilters) { - mLogFilters.addAll(newLogFilters); - } - - /** - * Unsubscribes all {@link LogFilter} associated with the logListenerIndex - * - * @param logListenerIndex the index of the logListener to unregister. - */ - synchronized void unsubscribeLogListener(int logListenerIndex) { - mLogFilters.removeIf(lf -> lf.getLogListenerIndex() == logListenerIndex); - } - - /** Starts the run method in a new thread if logcatReader isn't running already. */ - void startAsyncIfNotStarted() { - if (mRunning.compareAndSet(false, true)) { - mExecutor.execute(this::run); - } - } - - /** Gracefully stops {@link LogcatReader}. */ - synchronized void stop() { - mRunning.set(false); - mLogFilters.clear(); - } - - /** Builds a {@link LocalSocket} to read from {@code logdr}. */ - static LocalSocket buildLocalSocket() { - return new LocalSocket(LocalSocket.SOCKET_SEQPACKET); - } -} diff --git a/service/src/com/android/car/telemetry/proto/telemetry.proto b/service/src/com/android/car/telemetry/proto/telemetry.proto index 422c4a2c33..5787d62b9f 100644 --- a/service/src/com/android/car/telemetry/proto/telemetry.proto +++ b/service/src/com/android/car/telemetry/proto/telemetry.proto @@ -21,50 +21,35 @@ package com.android.car.telemetry; option java_package = "com.android.car.telemetry"; option java_outer_classname = "TelemetryProto"; -// A Tpk (Telemetry Package) manifest. -// It contains a script and the rules how the script runs on devices. -message Manifest { +// A metrics configuration. +// +// The metrics configuration describes a metric that is collected from a device. +// It includes a declarative part that configures the metric and the data publisher +// and a data handler to process the data and create a statistic. +// The latter is written in Lua language. +message MetricsConfig { // Required. - // Name of the Tpk, used to distinguish TPKs. + // The name of the configuration. Must be unique within a device. // Only alphanumeric and _ characters are allowed. Minimum length is 3 chars. optional string name = 1; // Required. - // A script that is executed in devices. Must contain all the functions - // defined in the listeners below. - optional string script = 2; + // Version number of the configuration. + optional int32 version = 2; // Required. - // A unique version number of the Tpk, used to distinguish between Tpks of the - // same name. - optional int32 version = 3; - - // Telemetry service subscribes these listeners to vehicle property change events. - // The functions must be present in the script. - repeated PropertyChangeListener property_change_listeners = 4; - - // Telemetry service subscribes these listeners to Android log (logcat) events. - // The functions must be present in the script. - repeated LogListener log_listeners = 5; - - // Telemetry service subscribes these listeners to stats anomalies, such as - // Alerts, Alarms, stats out-of-space anomaly and historical data anomaly. - // The number of listener is limited to 10 by statsd. - // The functions must be present in the script. - repeated StatsListener stats_listeners = 6; - - // Dumpsys result listeners can be registered to retrieve dump report for - // specified report types. - // The functions must be present in the script. - repeated DumpsysResultListener dumpsys_result_listeners = 7; + // A script that is executed in devices. Must contain all the handler functions + // defined in the listeners below. + // The script functions must be `pure` functions. + optional string script = 3; - // This timer executes functions when a specific event happens. - // The functions must be present in the script. - repeated Timer timers = 8; + // Required. + repeated Subscriber subscribers = 4; } -// A function that is executed when a vehicle property change events occur. -message PropertyChangeListener { +// Parameters for Vehicle Properties publisher. +// See https://source.android.com/devices/automotive/vhal/properties +message VehiclePropertyPublisher { // Required. // See packages/services/Car/car-lib/src/android/car/VehiclePropertyIds.java optional int32 vehicle_property_id = 1; @@ -73,197 +58,21 @@ message PropertyChangeListener { // packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java // look for constants SENSOR_RATE_*; optional float read_rate = 2; - - // Required. - optional string function_name = 3; } -// A function that receives Android log (logcat) events. The log event is passed -// as a string argument to the function. -// -// The LogListener will receive log events if the log event matches any of the -// "types" or "tags". -// -// Please see ../README.md for details. -// -// Example: -// function processException(log_event_line) ... end -message LogListener { - enum Type { - // Default value. - TYPE_UNSPECIFIED = 0; - - // Matches logged exceptions. - EXCEPTIONS = 1; +// Specifies data publisher and its parameters. +message Publisher { + oneof publisher { + VehiclePropertyPublisher vehicle_property = 1; } - - // Required. - // Unique name of the logListener within the Tpk. Used to - // subscribe/unsubscribe from log events. - optional string name = 1; - - // Required. - // Name of the function to be executed when the logs the logListener has a - // match with its filters - optional string function_name = 2; - - // Message types to listen to in LogCat. - // At least one "types" or "tags" must be provided. - repeated Type types = 3; - - // Tags to listen to in LogCat. - // At least one "types" or "tags" must be provided. - repeated string tags = 4; } -// A function that receives stats reports. -// -// LogProcessor App provides limited statsd support. Please see -// logprocessor/README.md for details. -// -// Script function semantics: -// -- Param report_list is a table with 1-1 mapping -// to ConfigMetricsReportList. -// -- Param extra_stats is a table { config_uid, config_key, ... } coming -// -- from PendingIntent described in StatsManager#setBroadcastSubscriber(). -// function onStatdEvent(report_list, extra_stats) end -message StatsListener { - // Function to be called when the subscriptions below get triggered. - optional string function_name = 1; - - // Serialized StatsdConfig defined in - // AOSP/frameworks/base/cmds/statsd/src/statsd_config.proto - // NOTE: Config ID and other generated IDs must be unique within this - // statsd_config. - optional bytes statsd_config = 2; - - // Subscribe the telemetry service to stats broadcast events: Alarms and Alerts. - // Subscriptions must be defined in the statsd_config as - // BroadcastSubscriberDetails. - // NOTE: It must be unique within the statsd_config. - optional int64 subscriber_id = 3; -} - -// A function that receives Dumpsys reports. -// -// The DumpsysResultListener will receive dumpsys reports of the specified -// DumpsysReportType -message DumpsysResultListener { - // Names of the system services that's allowed to run dumpsys on. - enum SystemServiceName { - UNSPECIFIED = 0; - - // Matches car service com.android.car.CarService. - CAR_SERVICE = 1; - - // Matches package manager service - // com.android.server.pm.PackageManagerService. - PACKAGE = 2; // - } - - // Required. - // Unique name of the DumpsysResultListener within the Tpk. - // Used to register the specific DumpsysResultListener needed. - optional string name = 1; - - // Required. - // Name of the function to be executed when a dumpsys report of the specified - // system services are retrieved. - optional string function_name = 2; - - // Required. - // System service to run dumpsys for. - optional SystemServiceName system_service_name = 3; - - // Extra arguments for dumpsys - optional string arguments = 4; -} - -// Runs a script function after some delay when an event happens. -message Timer { - enum TriggerType { - TRIGGER_TYPE_UNSPECIFIED = 0; - - // When the device boots up. - // - // Note that when device wakes up from a deep sleep (suspend to ram), this - // trigger doesn't work. - // - // It doesn't guarantee immediate activation of the timer right after the - // boot, only after the system and the script is ready. - // "initial_delay_millis" parameter denotes a delay from boot (not from - // the script is initialized and ready). - TRIGGER_TYPE_BOOT = 1; - } - - // Required. - // Name of the script function that will be executed. - optional string function_name = 1; - - // Required. - // An event trigger that activates this timer. - optional TriggerType trigger_type = 2; - - // Required. - // Delay after the trigger event before initial executing the function. - // - // Be careful putting long delays (>30 minutes), because the average - // driving duration might be shorter than the delay, and the function - // will be executed less frequently than desired amount. - optional int64 initial_delay_millis = 3; - - // The max number of times the function will be periodically executed. - // When this number of execution is reached, the timer will be stopped. - // 0 means the timer is disabled. - // -1 means the timer never stops. - optional int32 max_count = 4; - - // Time between successive function executions if max_count >= 2. - optional int64 period_millis = 5; -} - -// A message that encapsulates different types of error or log metadata as -// for informational and debugging purposes. -// -// When the app crashes or the system restarts, the timers will reset. -message SecularTrendsLog { - // Required. - optional int64 timestamp = 1; - - enum LogType { - // Default enum. - UNSPECIFIED = 0; - - // Used when manifest is misconfigurated, such as missing required fields. - MANIFEST_MISCONFIGURATION = 1; - - // Used when a Java service throws an exception. - JAVA_EXCEPTION = 2; - - // Used when LogProc service failes to bind to sandbox service. - SANDBOX_SERVICE_CONNECTION_FAILURE = 3; - - // Used when an error occurs in the native code. - NATIVE_RUNTIME_ERROR = 4; - - // Used when an error occurs while executing the Lua script (such as - // errors returned by lua_pcall) - LUA_RUNTIME_ERROR = 5; - - // Used when a service that telemetry service depends on crashes or fails. - DEPENDENT_SERVICE_FAILURE = 6; - } - - // Required. - // A type that indicates where the log is generated. - optional LogType type = 2; - - // Required. - // Human readable message explaining what’s wrong or how to fix it. - optional string message = 3; +// Specifies publisher with its parameters and the handler function that's invoked +// when data is received. The format of the data depends on the Publisher. +message Subscriber { + // Name of the script function that's invoked when this subscriber is triggered. + optional string handler = 1; - // Optional. - // If there is an exception, there will be stack trace. However this - // information is not always available. - optional string stack_trace = 4; + // Publisher and its parameters. + optional Publisher publisher = 2; } diff --git a/tests/carservice_unit_test/src/com/android/car/telemetry/CarTelemetryServiceTest.java b/tests/carservice_unit_test/src/com/android/car/telemetry/CarTelemetryServiceTest.java index d8bf9a2bc0..0e9a1689dd 100644 --- a/tests/carservice_unit_test/src/com/android/car/telemetry/CarTelemetryServiceTest.java +++ b/tests/carservice_unit_test/src/com/android/car/telemetry/CarTelemetryServiceTest.java @@ -40,8 +40,8 @@ public class CarTelemetryServiceTest { private final ManifestKey mManifestKeyV1 = new ManifestKey("Name", 1); private final ManifestKey mManifestKeyV2 = new ManifestKey("Name", 2); - private final TelemetryProto.Manifest mManifest = - TelemetryProto.Manifest.newBuilder().setScript("no-op").build(); + private final TelemetryProto.MetricsConfig mMetricsConfig = + TelemetryProto.MetricsConfig.newBuilder().setScript("no-op").build(); private CarTelemetryService mService; @@ -52,16 +52,16 @@ public class CarTelemetryServiceTest { @Test public void testAddManifest_newManifest_shouldSucceed() { - int result = mService.addManifest(mManifestKeyV1, mManifest.toByteArray()); + int result = mService.addManifest(mManifestKeyV1, mMetricsConfig.toByteArray()); assertThat(result).isEqualTo(CarTelemetryManager.ERROR_NONE); } @Test public void testAddManifest_duplicateManifest_shouldFail() { - mService.addManifest(mManifestKeyV1, mManifest.toByteArray()); + mService.addManifest(mManifestKeyV1, mMetricsConfig.toByteArray()); - int result = mService.addManifest(mManifestKeyV1, mManifest.toByteArray()); + int result = mService.addManifest(mManifestKeyV1, mMetricsConfig.toByteArray()); assertThat(result).isEqualTo(CarTelemetryManager.ERROR_SAME_MANIFEST_EXISTS); } @@ -75,25 +75,25 @@ public class CarTelemetryServiceTest { @Test public void testAddManifest_olderManifest_shouldFail() { - mService.addManifest(mManifestKeyV2, mManifest.toByteArray()); + mService.addManifest(mManifestKeyV2, mMetricsConfig.toByteArray()); - int result = mService.addManifest(mManifestKeyV1, mManifest.toByteArray()); + int result = mService.addManifest(mManifestKeyV1, mMetricsConfig.toByteArray()); assertThat(result).isEqualTo(CarTelemetryManager.ERROR_NEWER_MANIFEST_EXISTS); } @Test public void testAddManifest_newerManifest_shouldReplace() { - mService.addManifest(mManifestKeyV1, mManifest.toByteArray()); + mService.addManifest(mManifestKeyV1, mMetricsConfig.toByteArray()); - int result = mService.addManifest(mManifestKeyV2, mManifest.toByteArray()); + int result = mService.addManifest(mManifestKeyV2, mMetricsConfig.toByteArray()); assertThat(result).isEqualTo(CarTelemetryManager.ERROR_NONE); } @Test public void testRemoveManifest_manifestExists_shouldSucceed() { - mService.addManifest(mManifestKeyV1, mManifest.toByteArray()); + mService.addManifest(mManifestKeyV1, mMetricsConfig.toByteArray()); boolean result = mService.removeManifest(mManifestKeyV1); @@ -109,15 +109,15 @@ public class CarTelemetryServiceTest { @Test public void testRemoveAllManifests_shouldSucceed() { - mService.addManifest(mManifestKeyV1, mManifest.toByteArray()); - mService.addManifest(mManifestKeyV2, mManifest.toByteArray()); + mService.addManifest(mManifestKeyV1, mMetricsConfig.toByteArray()); + mService.addManifest(mManifestKeyV2, mMetricsConfig.toByteArray()); mService.removeAllManifests(); // verify that the manifests are cleared by adding them again, should succeed - int result = mService.addManifest(mManifestKeyV1, mManifest.toByteArray()); + int result = mService.addManifest(mManifestKeyV1, mMetricsConfig.toByteArray()); assertThat(result).isEqualTo(CarTelemetryManager.ERROR_NONE); - result = mService.addManifest(mManifestKeyV2, mManifest.toByteArray()); + result = mService.addManifest(mManifestKeyV2, mMetricsConfig.toByteArray()); assertThat(result).isEqualTo(CarTelemetryManager.ERROR_NONE); } } |