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

Commit 3cadf0d9 authored by Anna Trostanetski's avatar Anna Trostanetski Committed by Gerrit Code Review
Browse files

Merge "Implement stats logging for Compatibility API."

parents 3dc68a95 e36b1a14
Loading
Loading
Loading
Loading
+39 −0
Original line number Original line Diff line number Diff line
@@ -319,6 +319,9 @@ message Atom {
            217 [(log_from_module) = "permissioncontroller"];
            217 [(log_from_module) = "permissioncontroller"];
        PermissionAppsFragmentViewed permission_apps_fragment_viewed =
        PermissionAppsFragmentViewed permission_apps_fragment_viewed =
            218  [(log_from_module) = "permissioncontroller"];
            218  [(log_from_module) = "permissioncontroller"];

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


    // Pulled events will start at field 10000.
    // Pulled events will start at field 10000.
@@ -6779,3 +6782,39 @@ message PermissionAppsFragmentViewed {
    }
    }
    optional Category category = 6;
    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 Original line Diff line number Diff line
@@ -19,6 +19,9 @@ package android.app;
import android.compat.Compatibility;
import android.compat.Compatibility;
import android.os.Process;
import android.os.Process;
import android.util.Log;
import android.util.Log;
import android.util.StatsLog;

import com.android.internal.compat.ChangeReporter;


import java.util.Arrays;
import java.util.Arrays;


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

    private static final String TAG = "Compatibility";
    private static final String TAG = "Compatibility";


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


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


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


    protected boolean isChangeEnabled(long changeId) {
    protected boolean isChangeEnabled(long changeId) {
        if (Arrays.binarySearch(mDisabledChanges, changeId) < 0) {
        if (Arrays.binarySearch(mDisabledChanges, changeId) < 0) {
            // Not present in the disabled array
            // Not present in the disabled array
            reportChange(changeId);
            reportChange(changeId, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
            return true;
            return true;
        }
        }
        reportChange(changeId, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__DISABLED);
        return false;
        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 Original line 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 Original line Diff line number Diff line
@@ -19,7 +19,9 @@ package com.android.server.compat;
import android.content.Context;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.util.Slog;
import android.util.Slog;
import android.util.StatsLog;


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


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


    private final Context mContext;
    private final Context mContext;
    private final ChangeReporter mChangeReporter;


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


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


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


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