/* * Copyright (C) 2023 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.server.appsearch; import android.annotation.NonNull; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.server.appsearch.external.localstorage.stats.CallStats; import java.util.Map; import java.util.Objects; /** * Class containing configs for AppSearch task queue's rate limit. * *
Task queue total capacity is the total cost of tasks that AppSearch can accept onto its task * queue from all packages. This is configured with an integer value. * *
Task queue per-package capacity is the total cost of tasks that AppSearch can accept onto its * task queue from a single calling package. This config is passed in as a percentage of the total * capacity. * *
Each AppSearch API call has an associated integer cost that is configured by the API costs * string. API costs must be positive. The API costs string uses API_ENTRY_DELIMITER (';') to * separate API entries and has a string API name followed by API_COST_DELIMITER (':') and the * integer cost to define each entry. If an API's cost is not specified in the string, its cost is * set to DEFAULT_API_COST. e.g. A valid API cost string: "putDocument:5;query:1;setSchema:10". * *
If an API call has a higher cost, this means that the API consumes more of the task queue
* budget and fewer number of tasks can be placed on the task queue. An incoming API call from a
* calling package is dropped when the rate limit is exceeded, which happens when either: 1. Total
* cost of all API calls currently on the task queue + cost of incoming API call > task queue total
* capacity. OR 2. Total cost of all API calls currently on the task queue from the calling package
* + cost of incoming API call > task queue per-package capacity.
*/
public final class AppSearchRateLimitConfig {
@VisibleForTesting public static final int DEFAULT_API_COST = 1;
/**
* Creates an instance of {@link AppSearchRateLimitConfig}.
*
* @param totalCapacity configures total cost of tasks that AppSearch can accept onto its task
* queue from all packages.
* @param perPackageCapacityPercentage configures total cost of tasks that AppSearch can accept
* onto its task queue from a single calling package, as a percentage of totalCapacity.
* @param apiCostsString configures costs for each {@link CallStats.CallType}. The string should
* use API_ENTRY_DELIMITER (';') to separate entries, with each entry defined by the string
* API name followed by API_COST_DELIMITER (':'). e.g. "putDocument:5;query:1;setSchema:10"
*/
public static AppSearchRateLimitConfig create(
int totalCapacity, float perPackageCapacityPercentage, @NonNull String apiCostsString) {
Objects.requireNonNull(apiCostsString);
Map The range of the cost should be [0, taskQueueTotalCapacity]. Default API cost of 1 will be
* returned if the cost has not been configured for an API call.
*/
public int getApiCost(@CallStats.CallType int apiType) {
return mTaskQueueApiCosts.getOrDefault(apiType, DEFAULT_API_COST);
}
/** Returns an API costs map based on apiCostsString. */
private static Map