From da79f2a110a5b31ec18395d994ddd6024cdc4d0a Mon Sep 17 00:00:00 2001 From: Tej Singh Date: Mon, 8 Nov 2021 23:12:41 -0800 Subject: [PATCH] Create StatsBootstrapAtomService Design doc is at go/statsd-bootstrap-logging. Creates a proxy service for logging atoms from bootstrap processes to statsd. Service has one API, which converts StatsBootstrapAtom into StatsEvent and logs to statsd. This should only used by processes that start in the bootstrap namespace and cannot directly link statsd's libraries to log to statsd. Bug: 204889815 Test: booted, made sure binder service was published. Change-Id: I09709a30a42a7a398234c995324f62a0d62ad24f --- core/java/android/content/Context.java | 6 ++ .../os/IStatsBootstrapAtomService.aidl | 36 +++++++ core/java/android/os/StatsBootstrapAtom.aidl | 34 +++++++ .../android/os/StatsBootstrapAtomValue.aidl | 29 ++++++ .../bootstrap/StatsBootstrapAtomService.java | 98 +++++++++++++++++++ .../java/com/android/server/SystemServer.java | 7 ++ 6 files changed, 210 insertions(+) create mode 100644 core/java/android/os/IStatsBootstrapAtomService.aidl create mode 100644 core/java/android/os/StatsBootstrapAtom.aidl create mode 100644 core/java/android/os/StatsBootstrapAtomValue.aidl create mode 100644 services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 6885c10b48898..1907d18f56c54 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -5461,6 +5461,12 @@ public abstract class Context { */ public static final String STATS_COMPANION_SERVICE = "statscompanion"; + /** + * Service to assist statsd in logging atoms from bootstrap atoms. + * @hide + */ + public static final String STATS_BOOTSTRAP_ATOM_SERVICE = "statsbootstrap"; + /** * Use with {@link #getSystemService(String)} to retrieve an {@link android.app.StatsManager}. * @hide diff --git a/core/java/android/os/IStatsBootstrapAtomService.aidl b/core/java/android/os/IStatsBootstrapAtomService.aidl new file mode 100644 index 0000000000000..9d1df67fa19d4 --- /dev/null +++ b/core/java/android/os/IStatsBootstrapAtomService.aidl @@ -0,0 +1,36 @@ +/* + * Copyright 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 android.os; + +import android.os.StatsBootstrapAtom; + +/** + * IBootstrapAtomService interface exposes an interface for processes that launch in the + * bootstrap namespace to push atoms to statsd. + * + * @hide + */ +oneway interface IStatsBootstrapAtomService { + /** + * Push an atom to StatsBootstrapAtomService, which will forward it to statsd. + * + * @param atom - parcelled representation of the atom to log. + * + * Errors are reported as service specific errors. + */ + void reportBootstrapAtom(in StatsBootstrapAtom atom); +} \ No newline at end of file diff --git a/core/java/android/os/StatsBootstrapAtom.aidl b/core/java/android/os/StatsBootstrapAtom.aidl new file mode 100644 index 0000000000000..47500af8eebf1 --- /dev/null +++ b/core/java/android/os/StatsBootstrapAtom.aidl @@ -0,0 +1,34 @@ +/* + * Copyright 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 android.os; + +import android.os.StatsBootstrapAtomValue; + +/* + * Generic encapsulation of an atom for bootstrap processes to log. + * + * @hide + */ +parcelable StatsBootstrapAtom { + /* + * Atom ID. Must be between 1 - 10,000. + */ + int atomId; + /* + * Vector of fields in the order of the atom definition. + */ + StatsBootstrapAtomValue[] values; + } \ No newline at end of file diff --git a/core/java/android/os/StatsBootstrapAtomValue.aidl b/core/java/android/os/StatsBootstrapAtomValue.aidl new file mode 100644 index 0000000000000..a90dfa404ee96 --- /dev/null +++ b/core/java/android/os/StatsBootstrapAtomValue.aidl @@ -0,0 +1,29 @@ +/* + * Copyright 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 android.os; +/* + * Supported field types. + * + * @hide + */ +union StatsBootstrapAtomValue { + boolean boolValue; + int intValue; + long longValue; + float floatValue; + String stringValue; + byte[] bytesValue; +} \ No newline at end of file diff --git a/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java b/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java new file mode 100644 index 0000000000000..0d420a535415b --- /dev/null +++ b/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java @@ -0,0 +1,98 @@ +/* + * 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.server.stats.bootstrap; + +import android.content.Context; +import android.os.IStatsBootstrapAtomService; +import android.os.StatsBootstrapAtom; +import android.os.StatsBootstrapAtomValue; +import android.util.Slog; +import android.util.StatsEvent; +import android.util.StatsLog; + +import com.android.server.SystemService; + +/** + * Proxy service for logging pushed atoms to statsd + * + * @hide + */ +public class StatsBootstrapAtomService extends IStatsBootstrapAtomService.Stub { + + private static final String TAG = "StatsBootstrapAtomService"; + private static final boolean DEBUG = false; + + @Override + public void reportBootstrapAtom(StatsBootstrapAtom atom) { + if (atom.atomId < 1 || atom.atomId >= 10000) { + Slog.e(TAG, "Atom ID " + atom.atomId + " is not a valid atom ID"); + return; + } + StatsEvent.Builder builder = StatsEvent.newBuilder().setAtomId(atom.atomId); + for (StatsBootstrapAtomValue value : atom.values) { + switch (value.getTag()) { + case StatsBootstrapAtomValue.boolValue: + builder.writeBoolean(value.getBoolValue()); + break; + case StatsBootstrapAtomValue.intValue: + builder.writeInt(value.getIntValue()); + break; + case StatsBootstrapAtomValue.longValue: + builder.writeLong(value.getLongValue()); + break; + case StatsBootstrapAtomValue.floatValue: + builder.writeFloat(value.getFloatValue()); + break; + case StatsBootstrapAtomValue.stringValue: + builder.writeString(value.getStringValue()); + break; + case StatsBootstrapAtomValue.bytesValue: + builder.writeByteArray(value.getBytesValue()); + break; + default: + Slog.e(TAG, "Unexpected value type " + value.getTag() + + " when logging atom " + atom.atomId); + return; + + } + } + StatsLog.write(builder.usePooledBuffer().build()); + } + + /** + * Lifecycle and related code + */ + public static final class Lifecycle extends SystemService { + private StatsBootstrapAtomService mStatsBootstrapAtomService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mStatsBootstrapAtomService = new StatsBootstrapAtomService(); + try { + publishBinderService(Context.STATS_BOOTSTRAP_ATOM_SERVICE, + mStatsBootstrapAtomService); + if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_BOOTSTRAP_ATOM_SERVICE); + } catch (Exception e) { + Slog.e(TAG, "Failed to publishBinderService", e); + } + } + } + +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index aca7cc9070b17..4435637c9ad80 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -264,6 +264,8 @@ public final class SystemServer implements Dumpable { "com.android.server.stats.StatsCompanion$Lifecycle"; private static final String STATS_PULL_ATOM_SERVICE_CLASS = "com.android.server.stats.pull.StatsPullAtomService"; + private static final String STATS_BOOTSTRAP_ATOM_SERVICE_LIFECYCLE_CLASS = + "com.android.server.stats.bootstrap.StatsBootstrapAtomService$Lifecycle"; private static final String USB_SERVICE_CLASS = "com.android.server.usb.UsbService$Lifecycle"; private static final String MIDI_SERVICE_CLASS = @@ -2487,6 +2489,11 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(STATS_PULL_ATOM_SERVICE_CLASS); t.traceEnd(); + // Log atoms to statsd from bootstrap processes. + t.traceBegin("StatsBootstrapAtomService"); + mSystemServiceManager.startService(STATS_BOOTSTRAP_ATOM_SERVICE_LIFECYCLE_CLASS); + t.traceEnd(); + // Incidentd and dumpstated helper t.traceBegin("StartIncidentCompanionService"); mSystemServiceManager.startService(IncidentCompanionService.class);