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

Commit c0a4bee0 authored by Tom Chan's avatar Tom Chan Committed by Android (Google) Code Review
Browse files

Merge "Allow overriding data request rate limit window size from command line" into main

parents ccac8f88 6b94199b
Loading
Loading
Loading
Loading
+53 −1
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import com.android.server.pm.KnownPackages;
import com.android.server.utils.quota.MultiRateLimiter;

import java.io.FileDescriptor;
import java.time.Duration;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@@ -106,7 +107,7 @@ public class WearableSensingManagerService extends
    private final Context mContext;
    private final AtomicInteger mNextDataRequestObserverId = new AtomicInteger(1);
    private final Set<DataRequestObserverContext> mDataRequestObserverContexts = new HashSet<>();
    private final MultiRateLimiter mDataRequestRateLimiter;
    @NonNull private volatile MultiRateLimiter mDataRequestRateLimiter;
    volatile boolean mIsServiceEnabled;

    public WearableSensingManagerService(Context context) {
@@ -238,6 +239,57 @@ public class WearableSensingManagerService extends
        }
    }

    /**
     * Sets the window size used in data request rate limiting.
     *
     * <p>The new value will not be reflected in {@link
     * WearableSensingDataRequest#getRateLimitWindowSize()}.
     *
     * <p>{@code windowSize} will be automatically capped between
     * com.android.server.utils.quota.QuotaTracker#MIN_WINDOW_SIZE_MS and
     * com.android.server.utils.quota.QuotaTracker#MAX_WINDOW_SIZE_MS
     *
     * <p>The current rate limit will also be reset.
     *
     * <p>This method is only used for testing and must not be called in production code because
     * it effectively bypasses the rate limiting introduced to enhance privacy protection.
     */
    @VisibleForTesting
    void setDataRequestRateLimitWindowSize(@NonNull Duration windowSize) {
        Slog.w(
                TAG,
                TextUtils.formatSimple(
                        "Setting the data request rate limit window size to %s. This also resets"
                            + " the current limit and should only be callable from a test.",
                        windowSize));
        mDataRequestRateLimiter =
                new MultiRateLimiter.Builder(mContext)
                        .addRateLimit(WearableSensingDataRequest.getRateLimit(), windowSize)
                        .build();
    }

    /**
     * Resets the window size used in data request rate limiting back to the default value.
     *
     * <p>The current rate limit will also be reset.
     *
     * <p>This method is only used for testing and must not be called in production code because
     * it effectively bypasses the rate limiting introduced to enhance privacy protection.
     */
    @VisibleForTesting
    void resetDataRequestRateLimitWindowSize() {
        Slog.w(
                TAG,
                "Resetting the data request rate limit window size back to the default value. This"
                    + " also resets the current limit and should only be callable from a test.");
        mDataRequestRateLimiter =
                new MultiRateLimiter.Builder(mContext)
                        .addRateLimit(
                                WearableSensingDataRequest.getRateLimit(),
                                WearableSensingDataRequest.getRateLimitWindowSize())
                        .build();
    }

    private DataRequestObserverContext getDataRequestObserverContext(
            int dataType, int userId, PendingIntent dataRequestPendingIntent) {
        synchronized (mDataRequestObserverContexts) {
+24 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.util.Slog;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.time.Duration;

final class WearableSensingShellCommand extends ShellCommand {
    private static final String TAG = WearableSensingShellCommand.class.getSimpleName();
@@ -90,6 +91,8 @@ final class WearableSensingShellCommand extends ShellCommand {
                return getBoundPackageName();
            case "set-temporary-service":
                return setTemporaryService();
            case "set-data-request-rate-limit-window-size":
                return setDataRequestRateLimitWindowSize();
            default:
                return handleDefaultCommands(cmd);
        }
@@ -114,6 +117,11 @@ final class WearableSensingShellCommand extends ShellCommand {
        pw.println("  set-temporary-service USER_ID [PACKAGE_NAME] [COMPONENT_NAME DURATION]");
        pw.println("    Temporarily (for DURATION ms) changes the service implementation.");
        pw.println("    To reset, call with just the USER_ID argument.");
        pw.println("  set-data-request-rate-limit-window-size WINDOW_SIZE");
        pw.println("    Set the window size used in data request rate limiting to WINDOW_SIZE"
                + " seconds.");
        pw.println("    positive WINDOW_SIZE smaller than 20 will be automatically set to 20.");
        pw.println("    To reset, call with 0 or a negative WINDOW_SIZE.");
    }

    private int createDataStream() {
@@ -209,4 +217,20 @@ final class WearableSensingShellCommand extends ShellCommand {
        resultPrinter.println(componentName == null ? "" : componentName.getPackageName());
        return 0;
    }

    private int setDataRequestRateLimitWindowSize() {
        Slog.d(TAG, "setDataRequestRateLimitWindowSize");
        int windowSizeSeconds = Integer.parseInt(getNextArgRequired());
        if (windowSizeSeconds <= 0) {
            mService.resetDataRequestRateLimitWindowSize();
        } else {
            // 20 is the minimum window size supported by the rate limiter.
            // It is defined by com.android.server.utils.quota.QuotaTracker#MIN_WINDOW_SIZE_MS
            if (windowSizeSeconds < 20) {
                windowSizeSeconds = 20;
            }
            mService.setDataRequestRateLimitWindowSize(Duration.ofSeconds(windowSizeSeconds));
        }
        return 0;
    }
}