Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da79f2a1 authored by Tej Singh's avatar Tej Singh
Browse files

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
parent 74ef57b8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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
+36 −0
Original line number Diff line number Diff line
/*
 * 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
+34 −0
Original line number Diff line number Diff line
/*
 * 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
+29 −0
Original line number Diff line number Diff line
/*
 * 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
+98 −0
Original line number Diff line number Diff line
/*
 * 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);
            }
        }
    }

}
Loading