1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.am;
18 
19 import android.content.ContentResolver;
20 import android.database.ContentObserver;
21 import android.os.Handler;
22 import android.provider.Settings;
23 import android.util.KeyValueListParser;
24 import android.util.Slog;
25 import android.util.TimeUtils;
26 
27 import java.io.PrintWriter;
28 
29 /**
30  * Tunable parameters for broadcast dispatch policy
31  */
32 public class BroadcastConstants {
33     private static final String TAG = "BroadcastConstants";
34 
35     // Value element names within the Settings record
36     static final String KEY_TIMEOUT = "bcast_timeout";
37     static final String KEY_SLOW_TIME = "bcast_slow_time";
38     static final String KEY_DEFERRAL = "bcast_deferral";
39     static final String KEY_DEFERRAL_DECAY_FACTOR = "bcast_deferral_decay_factor";
40     static final String KEY_DEFERRAL_FLOOR = "bcast_deferral_floor";
41     static final String KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT =
42             "bcast_allow_bg_activity_start_timeout";
43 
44     // All time intervals are in milliseconds
45     private static final long DEFAULT_TIMEOUT = 10_000;
46     private static final long DEFAULT_SLOW_TIME = 5_000;
47     private static final long DEFAULT_DEFERRAL = 5_000;
48     private static final float DEFAULT_DEFERRAL_DECAY_FACTOR = 0.75f;
49     private static final long DEFAULT_DEFERRAL_FLOOR = 0;
50     private static final long DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT = 10_000;
51 
52     // All time constants are in milliseconds
53 
54     // Timeout period for this broadcast queue
55     public long TIMEOUT = DEFAULT_TIMEOUT;
56     // Handling time above which we declare that a broadcast recipient was "slow".  Any
57     // value <= zero is interpreted as disabling broadcast deferral policy entirely.
58     public long SLOW_TIME = DEFAULT_SLOW_TIME;
59     // How long to initially defer broadcasts, if an app is slow to handle one
60     public long DEFERRAL = DEFAULT_DEFERRAL;
61     // Decay factor for successive broadcasts' deferral time
62     public float DEFERRAL_DECAY_FACTOR = DEFAULT_DEFERRAL_DECAY_FACTOR;
63     // Minimum that the deferral time can decay to until the backlog fully clears
64     public long DEFERRAL_FLOOR = DEFAULT_DEFERRAL_FLOOR;
65     // For how long after a whitelisted receiver's start its process can start a background activity
66     public long ALLOW_BG_ACTIVITY_START_TIMEOUT = DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT;
67 
68     // Settings override tracking for this instance
69     private String mSettingsKey;
70     private SettingsObserver mSettingsObserver;
71     private ContentResolver mResolver;
72     private final KeyValueListParser mParser = new KeyValueListParser(',');
73 
74     class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)75         SettingsObserver(Handler handler) {
76             super(handler);
77         }
78 
79         @Override
onChange(boolean selfChange)80         public void onChange(boolean selfChange) {
81             updateConstants();
82         }
83     }
84 
85     // A given constants instance is configured to observe specific keys from which
86     // that instance's values are drawn.
BroadcastConstants(String settingsKey)87     public BroadcastConstants(String settingsKey) {
88         mSettingsKey = settingsKey;
89     }
90 
91     /**
92      * Spin up the observer lazily, since it can only happen once the settings provider
93      * has been brought into service
94      */
startObserving(Handler handler, ContentResolver resolver)95     public void startObserving(Handler handler, ContentResolver resolver) {
96         mResolver = resolver;
97 
98         mSettingsObserver = new SettingsObserver(handler);
99         mResolver.registerContentObserver(Settings.Global.getUriFor(mSettingsKey),
100                 false, mSettingsObserver);
101 
102         updateConstants();
103     }
104 
updateConstants()105     private void updateConstants() {
106         synchronized (mParser) {
107             try {
108                 mParser.setString(Settings.Global.getString(mResolver, mSettingsKey));
109             } catch (IllegalArgumentException e) {
110                 Slog.e(TAG, "Bad broadcast settings in key '" + mSettingsKey + "'", e);
111                 return;
112             }
113 
114             // Unspecified fields retain their current value rather than revert to default
115             TIMEOUT = mParser.getLong(KEY_TIMEOUT, TIMEOUT);
116             SLOW_TIME = mParser.getLong(KEY_SLOW_TIME, SLOW_TIME);
117             DEFERRAL = mParser.getLong(KEY_DEFERRAL, DEFERRAL);
118             DEFERRAL_DECAY_FACTOR = mParser.getFloat(KEY_DEFERRAL_DECAY_FACTOR,
119                     DEFERRAL_DECAY_FACTOR);
120             DEFERRAL_FLOOR = mParser.getLong(KEY_DEFERRAL_FLOOR, DEFERRAL_FLOOR);
121             ALLOW_BG_ACTIVITY_START_TIMEOUT = mParser.getLong(KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT,
122                     ALLOW_BG_ACTIVITY_START_TIMEOUT);
123         }
124     }
125 
126     /**
127      * Standard dumpsys support; invoked from BroadcastQueue dump
128      */
dump(PrintWriter pw)129     public void dump(PrintWriter pw) {
130         synchronized (mParser) {
131             pw.println();
132             pw.print("  Broadcast parameters (key=");
133             pw.print(mSettingsKey);
134             pw.print(", observing=");
135             pw.print(mSettingsObserver != null);
136             pw.println("):");
137 
138             pw.print("    "); pw.print(KEY_TIMEOUT); pw.print(" = ");
139             TimeUtils.formatDuration(TIMEOUT, pw);
140             pw.println();
141 
142             pw.print("    "); pw.print(KEY_SLOW_TIME); pw.print(" = ");
143             TimeUtils.formatDuration(SLOW_TIME, pw);
144             pw.println();
145 
146             pw.print("    "); pw.print(KEY_DEFERRAL); pw.print(" = ");
147             TimeUtils.formatDuration(DEFERRAL, pw);
148             pw.println();
149 
150             pw.print("    "); pw.print(KEY_DEFERRAL_DECAY_FACTOR); pw.print(" = ");
151             pw.println(DEFERRAL_DECAY_FACTOR);
152 
153             pw.print("    "); pw.print(KEY_DEFERRAL_FLOOR); pw.print(" = ");
154             TimeUtils.formatDuration(DEFERRAL_FLOOR, pw);
155 
156             pw.print("    "); pw.print(KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT); pw.print(" = ");
157             TimeUtils.formatDuration(ALLOW_BG_ACTIVITY_START_TIMEOUT, pw);
158             pw.println();
159         }
160     }
161 }
162