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

Commit e36b1a14 authored by atrost's avatar atrost
Browse files

Implement stats logging for Compatibility API.

Add a new atom and log from both the app process API and the system server API
Bug: 136794938
Bug: 138378110
Test: statsd_testdrive 228

Change-Id: I80f07d0beb30c779c4bce70bebf2bb4ab22f6bfe
Merged-In: I80f07d0beb30c779c4bce70bebf2bb4ab22f6bfe
parent 763cb463
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -319,6 +319,9 @@ message Atom {
            217 [(log_from_module) = "permissioncontroller"];
        PermissionAppsFragmentViewed permission_apps_fragment_viewed =
            218  [(log_from_module) = "permissioncontroller"];

        AppCompatibilityChangeReported app_compatibility_change_reported =
            228 [(allow_from_any_uid) = true];
    }

    // Pulled events will start at field 10000.
@@ -6779,3 +6782,39 @@ message PermissionAppsFragmentViewed {
    }
    optional Category category = 6;
}

/**
 * Logs when a compatibility change is affecting an app.
 *
 * Logged from:
 *   frameworks/base/core/java/android/app/AppCompatCallbacks.java and
 *   frameworks/base/services/core/java/com/android/server/compat/PlatformCompat.java
 */
message AppCompatibilityChangeReported {
    // The UID of the app being affected by the compatibilty change.
    optional int32 uid = 1 [(is_uid) = true];

    // The ID of the change affecting the app.
    optional int64 change_id = 2;

    enum State {
        UNKNOWN_STATE = 0;
        ENABLED = 1;
        DISABLED = 2;
        LOGGED = 3;
    }

    // The state of the change - if logged from gating whether it was enabled or disabled, or just
    // logged otherwise.
    optional State state = 3;

    enum Source {
        UNKNOWN_SOURCE = 0;
        APP_PROCESS = 1;
        SYSTEM_SERVER = 2;
    }

    // Where it was logged from.
    optional Source source = 4;

}
+16 −4
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package android.app;
import android.compat.Compatibility;
import android.os.Process;
import android.util.Log;
import android.util.StatsLog;

import com.android.internal.compat.ChangeReporter;

import java.util.Arrays;

@@ -28,10 +31,10 @@ import java.util.Arrays;
 * @hide
 */
public final class AppCompatCallbacks extends Compatibility.Callbacks {

    private static final String TAG = "Compatibility";

    private final long[] mDisabledChanges;
    private final ChangeReporter mChangeReporter;

    /**
     * Install this class into the current process.
@@ -45,20 +48,29 @@ public final class AppCompatCallbacks extends Compatibility.Callbacks {
    private AppCompatCallbacks(long[] disabledChanges) {
        mDisabledChanges = Arrays.copyOf(disabledChanges, disabledChanges.length);
        Arrays.sort(mDisabledChanges);
        mChangeReporter = new ChangeReporter();
    }

    protected void reportChange(long changeId) {
        Log.d(TAG, "Compat change reported: " + changeId + "; UID " + Process.myUid());
        // TODO log via StatsLog
        reportChange(changeId, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
    }

    protected boolean isChangeEnabled(long changeId) {
        if (Arrays.binarySearch(mDisabledChanges, changeId) < 0) {
            // Not present in the disabled array
            reportChange(changeId);
            reportChange(changeId, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
            return true;
        }
        reportChange(changeId, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED);
        return false;
    }

    private void reportChange(long changeId, int state) {
        int uid = Process.myUid();
        //TODO(b/138374585): Implement rate limiting for the logs.
        Log.d(TAG, ChangeReporter.createLogString(uid, changeId, state));
        mChangeReporter.reportChange(uid, changeId,
                state, /* source */StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__APP_PROCESS);
    }

}
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.internal.compat;

import android.util.StatsLog;

/**
 * A helper class to report changes to stats log.
 *
 * @hide
 */
public final class ChangeReporter {

    /**
     * Transforms StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE enum to a string.
     *
     * @param state to transform
     * @return a string representing the state
     */
    private static String stateToString(int state) {
        switch (state) {
            case StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED:
                return "LOGGED";
            case StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED:
                return "ENABLED";
            case StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED:
                return "DISABLED";
            default:
                return "UNKNOWN";
        }
    }

    /**
     * Constructs and returns a string to be logged to logcat when a change is reported.
     *
     * @param uid      affected by the change
     * @param changeId the reported change id
     * @param state    of the reported change - enabled/disabled/only logged
     * @return string to log
     */
    public static String createLogString(int uid, long changeId, int state) {
        return String.format("Compat change id reported: %d; UID %d; state: %s", changeId, uid,
                stateToString(state));
    }

    /**
     * Report the change to stats log.
     *
     * @param uid      affected by the change
     * @param changeId the reported change id
     * @param state    of the reported change - enabled/disabled/only logged
     * @param source   of the logging - app process or system server
     */
    public void reportChange(int uid, long changeId, int state, int source) {
        //TODO(b/138374585): Implement rate limiting for stats log.
        StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
                state, source);
    }
}
+18 −3
Original line number Diff line number Diff line
@@ -19,7 +19,9 @@ package com.android.server.compat;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.util.Slog;
import android.util.StatsLog;

import com.android.internal.compat.ChangeReporter;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.util.DumpUtils;

@@ -34,23 +36,27 @@ public class PlatformCompat extends IPlatformCompat.Stub {
    private static final String TAG = "Compatibility";

    private final Context mContext;
    private final ChangeReporter mChangeReporter;

    public PlatformCompat(Context context) {
        mContext = context;
        mChangeReporter = new ChangeReporter();
    }

    @Override
    public void reportChange(long changeId, ApplicationInfo appInfo) {
        Slog.d(TAG, "Compat change reported: " + changeId + "; UID " + appInfo.uid);
        // TODO log via StatsLog
        reportChange(changeId, appInfo, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
    }

    @Override
    public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
        if (CompatConfig.get().isChangeEnabled(changeId, appInfo)) {
            reportChange(changeId, appInfo);
            reportChange(changeId, appInfo,
                    StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
            return true;
        }
        reportChange(changeId, appInfo,
                StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED);
        return false;
    }

@@ -59,4 +65,13 @@ public class PlatformCompat extends IPlatformCompat.Stub {
        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
        CompatConfig.get().dumpConfig(pw);
    }

    private void reportChange(long changeId, ApplicationInfo appInfo, int state) {
        int uid = appInfo.uid;
        //TODO(b/138374585): Implement rate limiting for the logs.
        Slog.d(TAG, ChangeReporter.createLogString(uid, changeId, state));
        mChangeReporter.reportChange(uid, changeId,
                state, /* source */
                StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__SYSTEM_SERVER);
    }
}