Loading core/java/android/os/ZygoteProcess.java +45 −0 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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" }; Loading Loading @@ -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()) { Loading Loading @@ -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. */ Loading core/java/android/provider/Settings.java +11 −2 Original line number Diff line number Diff line Loading @@ -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. * core/java/com/android/internal/os/Zygote.java +3 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading core/java/com/android/internal/os/ZygoteArguments.java +15 −0 Original line number Diff line number Diff line Loading @@ -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 * Loading Loading @@ -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"); Loading core/java/com/android/internal/os/ZygoteConnection.java +39 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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() { Loading @@ -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, Loading Loading @@ -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); } } /** Loading @@ -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 Loading
core/java/android/os/ZygoteProcess.java +45 −0 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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" }; Loading Loading @@ -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()) { Loading Loading @@ -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. */ Loading
core/java/android/provider/Settings.java +11 −2 Original line number Diff line number Diff line Loading @@ -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. *
core/java/com/android/internal/os/Zygote.java +3 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading
core/java/com/android/internal/os/ZygoteArguments.java +15 −0 Original line number Diff line number Diff line Loading @@ -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 * Loading Loading @@ -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"); Loading
core/java/com/android/internal/os/ZygoteConnection.java +39 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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() { Loading @@ -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, Loading Loading @@ -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); } } /** Loading @@ -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