/*
|
* Copyright (C) 2018 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.am;
|
|
import android.content.ContentResolver;
|
import android.database.ContentObserver;
|
import android.os.Handler;
|
import android.provider.Settings;
|
import android.util.KeyValueListParser;
|
import android.util.Slog;
|
import android.util.TimeUtils;
|
|
import java.io.PrintWriter;
|
|
/**
|
* Tunable parameters for broadcast dispatch policy
|
*/
|
public class BroadcastConstants {
|
private static final String TAG = "BroadcastConstants";
|
|
// Value element names within the Settings record
|
static final String KEY_TIMEOUT = "bcast_timeout";
|
static final String KEY_SLOW_TIME = "bcast_slow_time";
|
static final String KEY_DEFERRAL = "bcast_deferral";
|
static final String KEY_DEFERRAL_DECAY_FACTOR = "bcast_deferral_decay_factor";
|
static final String KEY_DEFERRAL_FLOOR = "bcast_deferral_floor";
|
static final String KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT =
|
"bcast_allow_bg_activity_start_timeout";
|
|
// All time intervals are in milliseconds
|
private static final long DEFAULT_TIMEOUT = 10_000;
|
private static final long DEFAULT_SLOW_TIME = 5_000;
|
private static final long DEFAULT_DEFERRAL = 5_000;
|
private static final float DEFAULT_DEFERRAL_DECAY_FACTOR = 0.75f;
|
private static final long DEFAULT_DEFERRAL_FLOOR = 0;
|
private static final long DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT = 10_000;
|
|
// All time constants are in milliseconds
|
|
// Timeout period for this broadcast queue
|
public long TIMEOUT = DEFAULT_TIMEOUT;
|
// Handling time above which we declare that a broadcast recipient was "slow". Any
|
// value <= zero is interpreted as disabling broadcast deferral policy entirely.
|
public long SLOW_TIME = DEFAULT_SLOW_TIME;
|
// How long to initially defer broadcasts, if an app is slow to handle one
|
public long DEFERRAL = DEFAULT_DEFERRAL;
|
// Decay factor for successive broadcasts' deferral time
|
public float DEFERRAL_DECAY_FACTOR = DEFAULT_DEFERRAL_DECAY_FACTOR;
|
// Minimum that the deferral time can decay to until the backlog fully clears
|
public long DEFERRAL_FLOOR = DEFAULT_DEFERRAL_FLOOR;
|
// For how long after a whitelisted receiver's start its process can start a background activity
|
public long ALLOW_BG_ACTIVITY_START_TIMEOUT = DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT;
|
|
// Settings override tracking for this instance
|
private String mSettingsKey;
|
private SettingsObserver mSettingsObserver;
|
private ContentResolver mResolver;
|
private final KeyValueListParser mParser = new KeyValueListParser(',');
|
|
class SettingsObserver extends ContentObserver {
|
SettingsObserver(Handler handler) {
|
super(handler);
|
}
|
|
@Override
|
public void onChange(boolean selfChange) {
|
updateConstants();
|
}
|
}
|
|
// A given constants instance is configured to observe specific keys from which
|
// that instance's values are drawn.
|
public BroadcastConstants(String settingsKey) {
|
mSettingsKey = settingsKey;
|
}
|
|
/**
|
* Spin up the observer lazily, since it can only happen once the settings provider
|
* has been brought into service
|
*/
|
public void startObserving(Handler handler, ContentResolver resolver) {
|
mResolver = resolver;
|
|
mSettingsObserver = new SettingsObserver(handler);
|
mResolver.registerContentObserver(Settings.Global.getUriFor(mSettingsKey),
|
false, mSettingsObserver);
|
|
updateConstants();
|
}
|
|
private void updateConstants() {
|
synchronized (mParser) {
|
try {
|
mParser.setString(Settings.Global.getString(mResolver, mSettingsKey));
|
} catch (IllegalArgumentException e) {
|
Slog.e(TAG, "Bad broadcast settings in key '" + mSettingsKey + "'", e);
|
return;
|
}
|
|
// Unspecified fields retain their current value rather than revert to default
|
TIMEOUT = mParser.getLong(KEY_TIMEOUT, TIMEOUT);
|
SLOW_TIME = mParser.getLong(KEY_SLOW_TIME, SLOW_TIME);
|
DEFERRAL = mParser.getLong(KEY_DEFERRAL, DEFERRAL);
|
DEFERRAL_DECAY_FACTOR = mParser.getFloat(KEY_DEFERRAL_DECAY_FACTOR,
|
DEFERRAL_DECAY_FACTOR);
|
DEFERRAL_FLOOR = mParser.getLong(KEY_DEFERRAL_FLOOR, DEFERRAL_FLOOR);
|
ALLOW_BG_ACTIVITY_START_TIMEOUT = mParser.getLong(KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT,
|
ALLOW_BG_ACTIVITY_START_TIMEOUT);
|
}
|
}
|
|
/**
|
* Standard dumpsys support; invoked from BroadcastQueue dump
|
*/
|
public void dump(PrintWriter pw) {
|
synchronized (mParser) {
|
pw.println();
|
pw.print(" Broadcast parameters (key=");
|
pw.print(mSettingsKey);
|
pw.print(", observing=");
|
pw.print(mSettingsObserver != null);
|
pw.println("):");
|
|
pw.print(" "); pw.print(KEY_TIMEOUT); pw.print(" = ");
|
TimeUtils.formatDuration(TIMEOUT, pw);
|
pw.println();
|
|
pw.print(" "); pw.print(KEY_SLOW_TIME); pw.print(" = ");
|
TimeUtils.formatDuration(SLOW_TIME, pw);
|
pw.println();
|
|
pw.print(" "); pw.print(KEY_DEFERRAL); pw.print(" = ");
|
TimeUtils.formatDuration(DEFERRAL, pw);
|
pw.println();
|
|
pw.print(" "); pw.print(KEY_DEFERRAL_DECAY_FACTOR); pw.print(" = ");
|
pw.println(DEFERRAL_DECAY_FACTOR);
|
|
pw.print(" "); pw.print(KEY_DEFERRAL_FLOOR); pw.print(" = ");
|
TimeUtils.formatDuration(DEFERRAL_FLOOR, pw);
|
|
pw.print(" "); pw.print(KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT); pw.print(" = ");
|
TimeUtils.formatDuration(ALLOW_BG_ACTIVITY_START_TIMEOUT, pw);
|
pw.println();
|
}
|
}
|
}
|