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

Commit b9fadbfc authored by Andrei-Valentin Onea's avatar Andrei-Valentin Onea Committed by Android (Google) Code Review
Browse files

Merge "Add statslog logging for hidden api usage"

parents ea5e754c e8e150db
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -252,6 +252,11 @@ public class ZygoteProcess {
     */
    private int mHiddenApiAccessLogSampleRate;

    /**
     * Proportion of hidden API accesses that should be logged to statslog; 0 - 0x10000.
     */
    private int mHiddenApiAccessStatslogSampleRate;

    /**
     * The state of the connection to the primary zygote.
     */
@@ -487,6 +492,7 @@ public class ZygoteProcess {
        "--start-child-zygote",
        "--set-api-blacklist-exemptions",
        "--hidden-api-log-sampling-rate",
        "--hidden-api-statslog-sampling-rate",
        "--invoke-with"
    };

@@ -776,6 +782,21 @@ public class ZygoteProcess {
        }
    }

    /**
     * Set the precentage of detected hidden API accesses that are logged to the new event log.
     *
     * <p>This rate will take affect for all new processes forked from the zygote after this call.
     *
     * @param rate An integer between 0 and 0x10000 inclusive. 0 means no event logging.
     */
    public void setHiddenApiAccessStatslogSampleRate(int rate) {
        synchronized (mLock) {
            mHiddenApiAccessStatslogSampleRate = rate;
            maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState);
            maybeSetHiddenApiAccessStatslogSampleRate(secondaryZygoteState);
        }
    }

    @GuardedBy("mLock")
    private boolean maybeSetApiBlacklistExemptions(ZygoteState state, boolean sendIfEmpty) {
        if (state == null || state.isClosed()) {
@@ -830,6 +851,30 @@ public class ZygoteProcess {
        }
    }

    private void maybeSetHiddenApiAccessStatslogSampleRate(ZygoteState state) {
        if (state == null || state.isClosed()) {
            return;
        }
        if (mHiddenApiAccessStatslogSampleRate == -1) {
            return;
        }
        try {
            state.mZygoteOutputWriter.write(Integer.toString(1));
            state.mZygoteOutputWriter.newLine();
            state.mZygoteOutputWriter.write("--hidden-api-statslog-sampling-rate="
                    + Integer.toString(mHiddenApiAccessStatslogSampleRate));
            state.mZygoteOutputWriter.newLine();
            state.mZygoteOutputWriter.flush();
            int status = state.mZygoteInputStream.readInt();
            if (status != 0) {
                Slog.e(LOG_TAG, "Failed to set hidden API statslog sampling rate; status "
                        + status);
            }
        } catch (IOException ioe) {
            Slog.e(LOG_TAG, "Failed to set hidden API statslog sampling rate", ioe);
        }
    }

    /**
     * Creates a ZygoteState for the primary zygote if it doesn't exist or has been disconnected.
     */
+11 −2
Original line number Diff line number Diff line
@@ -13376,14 +13376,23 @@ public final class Settings {
                "hidden_api_blacklist_exemptions";
        /**
         * Sampling rate for hidden API access event logs, as an integer in the range 0 to 0x10000
         * inclusive.
         * Sampling rate for hidden API access event logs with libmetricslogger, as an integer in
         * the range 0 to 0x10000 inclusive.
         *
         * @hide
         */
        public static final String HIDDEN_API_ACCESS_LOG_SAMPLING_RATE =
                "hidden_api_access_log_sampling_rate";
        /**
         * Sampling rate for hidden API access event logging with statslog, as an integer in the
         * range 0 to 0x10000 inclusive.
         *
         * @hide
         */
        public static final String HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE =
                "hidden_api_access_statslog_sampling_rate";
        /**
         * Hidden API enforcement policy for apps.
         *
+3 −0
Original line number Diff line number Diff line
@@ -645,6 +645,9 @@ public final class Zygote {
        } else if (args.mHiddenApiAccessLogSampleRate != -1) {
            throw new IllegalArgumentException(
                BLASTULA_ERROR_PREFIX + "--hidden-api-log-sampling-rate=");
        } else if (args.mHiddenApiAccessStatslogSampleRate != -1) {
            throw new IllegalArgumentException(
                BLASTULA_ERROR_PREFIX + "--hidden-api-statslog-sampling-rate=");
        } else if (args.mInvokeWith != null) {
            throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--invoke-with");
        } else if (args.mPermittedCapabilities != 0 || args.mEffectiveCapabilities != 0) {
+15 −0
Original line number Diff line number Diff line
@@ -204,6 +204,12 @@ class ZygoteArguments {
     */
    int mHiddenApiAccessLogSampleRate = -1;

    /**
     * Sampling rate for logging hidden API accesses to statslog. This is sent to the
     * pre-forked zygote at boot time, or when it changes, via --hidden-api-statslog-sampling-rate.
     */
    int mHiddenApiAccessStatslogSampleRate = -1;

    /**
     * Constructs instance and parses args
     *
@@ -391,6 +397,15 @@ class ZygoteArguments {
                        "Invalid log sampling rate: " + rateStr, nfe);
                }
                expectRuntimeArgs = false;
            } else if (arg.startsWith("--hidden-api-statslog-sampling-rate=")) {
                String rateStr = arg.substring(arg.indexOf('=') + 1);
                try {
                    mHiddenApiAccessStatslogSampleRate = Integer.parseInt(rateStr);
                } catch (NumberFormatException nfe) {
                    throw new IllegalArgumentException(
                        "Invalid statslog sampling rate: " + rateStr, nfe);
                }
                expectRuntimeArgs = false;
            } else if (arg.startsWith("--package-name=")) {
                if (mPackageName != null) {
                    throw new IllegalArgumentException("Duplicate arg specified");
+39 −7
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.system.ErrnoException;
import android.system.Os;
import android.system.StructPollfd;
import android.util.Log;
import android.util.StatsLog;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -192,9 +193,11 @@ class ZygoteConnection {
            return handleApiBlacklistExemptions(zygoteServer, parsedArgs.mApiBlacklistExemptions);
        }

        if (parsedArgs.mHiddenApiAccessLogSampleRate != -1) {
        if (parsedArgs.mHiddenApiAccessLogSampleRate != -1
                || parsedArgs.mHiddenApiAccessStatslogSampleRate != -1) {
            return handleHiddenApiAccessLogSampleRate(zygoteServer,
                    parsedArgs.mHiddenApiAccessLogSampleRate);
                    parsedArgs.mHiddenApiAccessLogSampleRate,
                    parsedArgs.mHiddenApiAccessStatslogSampleRate);
        }

        if (parsedArgs.mPermittedCapabilities != 0 || parsedArgs.mEffectiveCapabilities != 0) {
@@ -396,9 +399,11 @@ class ZygoteConnection {
        private final MetricsLogger mMetricsLogger = new MetricsLogger();
        private static HiddenApiUsageLogger sInstance = new HiddenApiUsageLogger();
        private int mHiddenApiAccessLogSampleRate = 0;
        private int mHiddenApiAccessStatslogSampleRate = 0;

        public static void setHiddenApiAccessLogSampleRate(int sampleRate) {
        public static void setHiddenApiAccessLogSampleRates(int sampleRate, int newSampleRate) {
            sInstance.mHiddenApiAccessLogSampleRate = sampleRate;
            sInstance.mHiddenApiAccessStatslogSampleRate = newSampleRate;
        }

        public static HiddenApiUsageLogger getInstance() {
@@ -410,6 +415,9 @@ class ZygoteConnection {
            if (sampledValue < mHiddenApiAccessLogSampleRate) {
                logUsage(packageName, signature, accessMethod, accessDenied);
            }
            if (sampledValue < mHiddenApiAccessStatslogSampleRate) {
                newLogUsage(signature, accessMethod, accessDenied);
            }
        }

        private void logUsage(String packageName, String signature, int accessMethod,
@@ -439,6 +447,27 @@ class ZygoteConnection {
            }
            mMetricsLogger.write(logMaker);
        }

        private void newLogUsage(String signature, int accessMethod, boolean accessDenied) {
            int accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__NONE;
            switch(accessMethod) {
                case HiddenApiUsageLogger.ACCESS_METHOD_NONE:
                    accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__NONE;
                    break;
                case HiddenApiUsageLogger.ACCESS_METHOD_REFLECTION:
                    accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__REFLECTION;
                    break;
                case HiddenApiUsageLogger.ACCESS_METHOD_JNI:
                    accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__JNI;
                    break;
                case HiddenApiUsageLogger.ACCESS_METHOD_LINKING:
                    accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__LINKING;
                    break;
            }
            int uid = Process.myUid();
            StatsLog.write(StatsLog.HIDDEN_API_USED, uid, signature,
                                   accessMethodProto, accessDenied);
        }
    }

    /**
@@ -450,15 +479,18 @@ class ZygoteConnection {
     * a Runnable object that must be returned to ZygoteServer.runSelectLoop to be invoked.
     *
     * @param zygoteServer  The server object that received the request
     * @param samplingRate  The new sample rate
     * @param samplingRate  The new sample rate for regular logging
     * @param statsdSamplingRate  The new sample rate for statslog logging
     * @return A Runnable object representing a new app in any blastulas spawned from here; the
     *         zygote process will always receive a null value from this function.
     */
    private Runnable handleHiddenApiAccessLogSampleRate(ZygoteServer zygoteServer,
            int samplingRate) {
            int samplingRate, int statsdSamplingRate) {
        return stateChangeWithBlastulaPoolReset(zygoteServer, () -> {
            ZygoteInit.setHiddenApiAccessLogSampleRate(samplingRate);
            HiddenApiUsageLogger.setHiddenApiAccessLogSampleRate(samplingRate);
            int maxSamplingRate = Math.max(samplingRate, statsdSamplingRate);
            ZygoteInit.setHiddenApiAccessLogSampleRate(maxSamplingRate);
            HiddenApiUsageLogger.setHiddenApiAccessLogSampleRates(samplingRate,
                    statsdSamplingRate);
            ZygoteInit.setHiddenApiUsageLogger(HiddenApiUsageLogger.getInstance());
        });
    }
Loading