blob: 9a00055e0079b61e6841e39779370997a332be50 [file] [log] [blame]
paulhu845456e2021-03-17 17:19:09 +08001/*
2 * Copyright (C) 2021 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
17package android.net;
18
paulhu94430952021-03-23 00:24:50 +080019import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER;
20import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE;
21import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY;
22import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
23import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
24import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
25
paulhuc9925e02021-03-17 20:30:33 +080026import android.annotation.IntDef;
paulhu94430952021-03-23 00:24:50 +080027import android.annotation.IntRange;
28import android.annotation.NonNull;
29import android.annotation.Nullable;
30import android.annotation.SystemApi;
31import android.content.Context;
32import android.net.ConnectivityManager.MultipathPreference;
33import android.net.ConnectivityManager.PrivateDnsMode;
34import android.provider.Settings;
35import android.text.TextUtils;
36import android.util.Range;
37
38import com.android.net.module.util.ProxyUtils;
paulhuc9925e02021-03-17 20:30:33 +080039
40import java.lang.annotation.Retention;
41import java.lang.annotation.RetentionPolicy;
paulhu94430952021-03-23 00:24:50 +080042import java.time.Duration;
43import java.util.List;
paulhuc9925e02021-03-17 20:30:33 +080044
paulhu845456e2021-03-17 17:19:09 +080045/**
46 * A manager class for connectivity module settings.
47 *
48 * @hide
49 */
paulhu94430952021-03-23 00:24:50 +080050@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
paulhu845456e2021-03-17 17:19:09 +080051public class ConnectivitySettingsManager {
52
53 private ConnectivitySettingsManager() {}
54
paulhuc9925e02021-03-17 20:30:33 +080055 /** Data activity timeout settings */
56
57 /**
58 * Inactivity timeout to track mobile data activity.
59 *
60 * If set to a positive integer, it indicates the inactivity timeout value in seconds to
61 * infer the data activity of mobile network. After a period of no activity on mobile
62 * networks with length specified by the timeout, an {@code ACTION_DATA_ACTIVITY_CHANGE}
63 * intent is fired to indicate a transition of network status from "active" to "idle". Any
64 * subsequent activity on mobile networks triggers the firing of {@code
65 * ACTION_DATA_ACTIVITY_CHANGE} intent indicating transition from "idle" to "active".
66 *
67 * Network activity refers to transmitting or receiving data on the network interfaces.
68 *
69 * Tracking is disabled if set to zero or negative value.
paulhu94430952021-03-23 00:24:50 +080070 *
71 * @hide
paulhuc9925e02021-03-17 20:30:33 +080072 */
73 public static final String DATA_ACTIVITY_TIMEOUT_MOBILE = "data_activity_timeout_mobile";
74
75 /**
76 * Timeout to tracking Wifi data activity. Same as {@code DATA_ACTIVITY_TIMEOUT_MOBILE}
77 * but for Wifi network.
paulhu94430952021-03-23 00:24:50 +080078 *
79 * @hide
paulhuc9925e02021-03-17 20:30:33 +080080 */
81 public static final String DATA_ACTIVITY_TIMEOUT_WIFI = "data_activity_timeout_wifi";
82
83 /** Dns resolver settings */
84
85 /**
86 * Sample validity in seconds to configure for the system DNS resolver.
paulhu94430952021-03-23 00:24:50 +080087 *
88 * @hide
paulhuc9925e02021-03-17 20:30:33 +080089 */
90 public static final String DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS =
91 "dns_resolver_sample_validity_seconds";
92
93 /**
94 * Success threshold in percent for use with the system DNS resolver.
paulhu94430952021-03-23 00:24:50 +080095 *
96 * @hide
paulhuc9925e02021-03-17 20:30:33 +080097 */
98 public static final String DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT =
99 "dns_resolver_success_threshold_percent";
100
101 /**
102 * Minimum number of samples needed for statistics to be considered meaningful in the
103 * system DNS resolver.
paulhu94430952021-03-23 00:24:50 +0800104 *
105 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800106 */
107 public static final String DNS_RESOLVER_MIN_SAMPLES = "dns_resolver_min_samples";
108
109 /**
110 * Maximum number taken into account for statistics purposes in the system DNS resolver.
paulhu94430952021-03-23 00:24:50 +0800111 *
112 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800113 */
114 public static final String DNS_RESOLVER_MAX_SAMPLES = "dns_resolver_max_samples";
115
paulhu94430952021-03-23 00:24:50 +0800116 private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
117 private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
118
paulhuc9925e02021-03-17 20:30:33 +0800119 /** Network switch notification settings */
120
121 /**
122 * The maximum number of notifications shown in 24 hours when switching networks.
paulhu94430952021-03-23 00:24:50 +0800123 *
124 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800125 */
126 public static final String NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT =
127 "network_switch_notification_daily_limit";
128
129 /**
130 * The minimum time in milliseconds between notifications when switching networks.
paulhu94430952021-03-23 00:24:50 +0800131 *
132 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800133 */
134 public static final String NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS =
135 "network_switch_notification_rate_limit_millis";
136
137 /** Captive portal settings */
138
139 /**
140 * The URL used for HTTP captive portal detection upon a new connection.
141 * A 204 response code from the server is used for validation.
paulhu94430952021-03-23 00:24:50 +0800142 *
143 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800144 */
145 public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
146
147 /**
148 * What to do when connecting a network that presents a captive portal.
paulhu94430952021-03-23 00:24:50 +0800149 * Must be one of the CAPTIVE_PORTAL_MODE_* constants below.
paulhuc9925e02021-03-17 20:30:33 +0800150 *
151 * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
paulhu94430952021-03-23 00:24:50 +0800152 *
153 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800154 */
155 public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
156
157 /**
158 * Don't attempt to detect captive portals.
159 */
160 public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
161
162 /**
163 * When detecting a captive portal, display a notification that
164 * prompts the user to sign in.
165 */
166 public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
167
168 /**
169 * When detecting a captive portal, immediately disconnect from the
170 * network and do not reconnect to that network in the future.
171 */
172 public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
173
174 /** @hide */
175 @Retention(RetentionPolicy.SOURCE)
176 @IntDef(value = {
177 CAPTIVE_PORTAL_MODE_IGNORE,
178 CAPTIVE_PORTAL_MODE_PROMPT,
179 CAPTIVE_PORTAL_MODE_AVOID,
180 })
181 public @interface CaptivePortalMode {}
182
183 /** Global http proxy settings */
184
185 /**
186 * Host name for global http proxy. Set via ConnectivityManager.
paulhu94430952021-03-23 00:24:50 +0800187 *
188 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800189 */
190 public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host";
191
192 /**
193 * Integer host port for global http proxy. Set via ConnectivityManager.
paulhu94430952021-03-23 00:24:50 +0800194 *
195 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800196 */
197 public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port";
198
199 /**
200 * Exclusion list for global proxy. This string contains a list of
201 * comma-separated domains where the global proxy does not apply.
202 * Domains should be listed in a comma- separated list. Example of
203 * acceptable formats: ".domain1.com,my.domain2.com" Use
204 * ConnectivityManager to set/get.
paulhu94430952021-03-23 00:24:50 +0800205 *
206 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800207 */
208 public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST =
209 "global_http_proxy_exclusion_list";
210
211 /**
212 * The location PAC File for the proxy.
paulhu94430952021-03-23 00:24:50 +0800213 *
214 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800215 */
216 public static final String GLOBAL_HTTP_PROXY_PAC = "global_proxy_pac_url";
217
218 /** Private dns settings */
219
220 /**
221 * The requested Private DNS mode (string), and an accompanying specifier (string).
222 *
223 * Currently, the specifier holds the chosen provider name when the mode requests
224 * a specific provider. It may be used to store the provider name even when the
225 * mode changes so that temporarily disabling and re-enabling the specific
226 * provider mode does not necessitate retyping the provider hostname.
paulhu94430952021-03-23 00:24:50 +0800227 *
228 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800229 */
230 public static final String PRIVATE_DNS_MODE = "private_dns_mode";
231
232 /**
233 * The specific Private DNS provider name.
paulhu94430952021-03-23 00:24:50 +0800234 *
235 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800236 */
237 public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier";
238
239 /**
240 * Forced override of the default mode (hardcoded as "automatic", nee "opportunistic").
241 * This allows changing the default mode without effectively disabling other modes,
242 * all of which require explicit user action to enable/configure. See also b/79719289.
243 *
244 * Value is a string, suitable for assignment to PRIVATE_DNS_MODE above.
paulhu94430952021-03-23 00:24:50 +0800245 *
246 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800247 */
248 public static final String PRIVATE_DNS_DEFAULT_MODE = "private_dns_default_mode";
249
250 /** Other settings */
251
252 /**
253 * The number of milliseconds to hold on to a PendingIntent based request. This delay gives
254 * the receivers of the PendingIntent an opportunity to make a new network request before
255 * the Network satisfying the request is potentially removed.
paulhu94430952021-03-23 00:24:50 +0800256 *
257 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800258 */
259 public static final String CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS =
260 "connectivity_release_pending_intent_delay_ms";
261
262 /**
263 * Whether the mobile data connection should remain active even when higher
264 * priority networks like WiFi are active, to help make network switching faster.
265 *
266 * See ConnectivityService for more info.
267 *
268 * (0 = disabled, 1 = enabled)
paulhu94430952021-03-23 00:24:50 +0800269 *
270 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800271 */
272 public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
273
274 /**
275 * Whether the wifi data connection should remain active even when higher
276 * priority networks like Ethernet are active, to keep both networks.
277 * In the case where higher priority networks are connected, wifi will be
278 * unused unless an application explicitly requests to use it.
279 *
280 * See ConnectivityService for more info.
281 *
282 * (0 = disabled, 1 = enabled)
paulhu94430952021-03-23 00:24:50 +0800283 *
284 * @hide
paulhuc9925e02021-03-17 20:30:33 +0800285 */
286 public static final String WIFI_ALWAYS_REQUESTED = "wifi_always_requested";
287
paulhu845456e2021-03-17 17:19:09 +0800288 /**
289 * Whether to automatically switch away from wifi networks that lose Internet access.
290 * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always
291 * avoids such networks. Valid values are:
292 *
293 * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013.
294 * null: Ask the user whether to switch away from bad wifi.
295 * 1: Avoid bad wifi.
paulhu94430952021-03-23 00:24:50 +0800296 *
297 * @hide
paulhu845456e2021-03-17 17:19:09 +0800298 */
299 public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi";
300
301 /**
paulhu94430952021-03-23 00:24:50 +0800302 * Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013.
303 */
304 public static final int NETWORK_AVOID_BAD_WIFI_IGNORE = 0;
305
306 /**
307 * Ask the user whether to switch away from bad wifi.
308 */
309 public static final int NETWORK_AVOID_BAD_WIFI_PROMPT = 1;
310
311 /**
312 * Avoid bad wifi.
313 */
314 public static final int NETWORK_AVOID_BAD_WIFI_AVOID = 2;
315
316 /** @hide */
317 @Retention(RetentionPolicy.SOURCE)
318 @IntDef(value = {
319 NETWORK_AVOID_BAD_WIFI_IGNORE,
320 NETWORK_AVOID_BAD_WIFI_PROMPT,
321 NETWORK_AVOID_BAD_WIFI_AVOID,
322 })
323 public @interface NetworkAvoidBadWifi {}
324
325 /**
paulhu845456e2021-03-17 17:19:09 +0800326 * User setting for ConnectivityManager.getMeteredMultipathPreference(). This value may be
327 * overridden by the system based on device or application state. If null, the value
328 * specified by config_networkMeteredMultipathPreference is used.
paulhu94430952021-03-23 00:24:50 +0800329 *
330 * @hide
paulhu845456e2021-03-17 17:19:09 +0800331 */
332 public static final String NETWORK_METERED_MULTIPATH_PREFERENCE =
333 "network_metered_multipath_preference";
paulhu94430952021-03-23 00:24:50 +0800334
335 /**
paulhu7a4eeed2021-03-25 13:17:58 +0800336 * A list of apps that should go on cellular networks in preference even when higher-priority
337 * networks are connected.
338 *
339 * @hide
340 */
341 public static final String MOBILE_DATA_PREFERRED_APPS = "mobile_data_preferred_apps";
342
343 /**
paulhu94430952021-03-23 00:24:50 +0800344 * Get mobile data activity timeout from {@link Settings}.
345 *
346 * @param context The {@link Context} to query the setting.
347 * @param def The default timeout if no setting value.
348 * @return The {@link Duration} of timeout to track mobile data activity.
349 */
350 @NonNull
351 public static Duration getMobileDataActivityTimeout(@NonNull Context context,
352 @NonNull Duration def) {
353 final int timeout = Settings.Global.getInt(
354 context.getContentResolver(), DATA_ACTIVITY_TIMEOUT_MOBILE, (int) def.getSeconds());
355 return Duration.ofSeconds(timeout);
356 }
357
358 /**
359 * Set mobile data activity timeout to {@link Settings}.
360 * Tracking is disabled if set to zero or negative value.
361 *
362 * Note: Only use the number of seconds in this duration, lower second(nanoseconds) will be
363 * ignored.
364 *
365 * @param context The {@link Context} to set the setting.
366 * @param timeout The mobile data activity timeout.
367 */
368 public static void setMobileDataActivityTimeout(@NonNull Context context,
369 @NonNull Duration timeout) {
370 Settings.Global.putInt(context.getContentResolver(), DATA_ACTIVITY_TIMEOUT_MOBILE,
371 (int) timeout.getSeconds());
372 }
373
374 /**
375 * Get wifi data activity timeout from {@link Settings}.
376 *
377 * @param context The {@link Context} to query the setting.
378 * @param def The default timeout if no setting value.
379 * @return The {@link Duration} of timeout to track wifi data activity.
380 */
381 @NonNull
382 public static Duration getWifiDataActivityTimeout(@NonNull Context context,
383 @NonNull Duration def) {
384 final int timeout = Settings.Global.getInt(
385 context.getContentResolver(), DATA_ACTIVITY_TIMEOUT_WIFI, (int) def.getSeconds());
386 return Duration.ofSeconds(timeout);
387 }
388
389 /**
390 * Set wifi data activity timeout to {@link Settings}.
391 * Tracking is disabled if set to zero or negative value.
392 *
393 * Note: Only use the number of seconds in this duration, lower second(nanoseconds) will be
394 * ignored.
395 *
396 * @param context The {@link Context} to set the setting.
397 * @param timeout The wifi data activity timeout.
398 */
399 public static void setWifiDataActivityTimeout(@NonNull Context context,
400 @NonNull Duration timeout) {
401 Settings.Global.putInt(context.getContentResolver(), DATA_ACTIVITY_TIMEOUT_WIFI,
402 (int) timeout.getSeconds());
403 }
404
405 /**
406 * Get dns resolver sample validity duration from {@link Settings}.
407 *
408 * @param context The {@link Context} to query the setting.
409 * @param def The default duration if no setting value.
410 * @return The {@link Duration} of sample validity duration to configure for the system DNS
411 * resolver.
412 */
413 @NonNull
414 public static Duration getDnsResolverSampleValidityDuration(@NonNull Context context,
415 @NonNull Duration def) {
416 final int duration = Settings.Global.getInt(context.getContentResolver(),
417 DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, (int) def.getSeconds());
418 return Duration.ofSeconds(duration);
419 }
420
421 /**
422 * Set dns resolver sample validity duration to {@link Settings}. The duration must be a
423 * positive number of seconds.
424 *
425 * @param context The {@link Context} to set the setting.
426 * @param duration The sample validity duration.
427 */
428 public static void setDnsResolverSampleValidityDuration(@NonNull Context context,
429 @NonNull Duration duration) {
430 final int time = (int) duration.getSeconds();
431 if (time <= 0) {
432 throw new IllegalArgumentException("Invalid duration");
433 }
434 Settings.Global.putInt(
435 context.getContentResolver(), DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, time);
436 }
437
438 /**
439 * Get dns resolver success threshold percent from {@link Settings}.
440 *
441 * @param context The {@link Context} to query the setting.
442 * @param def The default value if no setting value.
443 * @return The success threshold in percent for use with the system DNS resolver.
444 */
445 public static int getDnsResolverSuccessThresholdPercent(@NonNull Context context, int def) {
446 return Settings.Global.getInt(
447 context.getContentResolver(), DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, def);
448 }
449
450 /**
451 * Set dns resolver success threshold percent to {@link Settings}. The threshold percent must
452 * be 0~100.
453 *
454 * @param context The {@link Context} to set the setting.
455 * @param percent The success threshold percent.
456 */
457 public static void setDnsResolverSuccessThresholdPercent(@NonNull Context context,
458 @IntRange(from = 0, to = 100) int percent) {
459 if (percent < 0 || percent > 100) {
460 throw new IllegalArgumentException("Percent must be 0~100");
461 }
462 Settings.Global.putInt(
463 context.getContentResolver(), DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, percent);
464 }
465
466 /**
467 * Get dns resolver samples range from {@link Settings}.
468 *
469 * @param context The {@link Context} to query the setting.
470 * @return The {@link Range<Integer>} of samples needed for statistics to be considered
471 * meaningful in the system DNS resolver.
472 */
473 @NonNull
474 public static Range<Integer> getDnsResolverSampleRanges(@NonNull Context context) {
475 final int minSamples = Settings.Global.getInt(context.getContentResolver(),
476 DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
477 final int maxSamples = Settings.Global.getInt(context.getContentResolver(),
478 DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
479 return new Range<>(minSamples, maxSamples);
480 }
481
482 /**
483 * Set dns resolver samples range to {@link Settings}.
484 *
485 * @param context The {@link Context} to set the setting.
486 * @param range The samples range. The minimum number should be more than 0 and the maximum
487 * number should be less that 64.
488 */
489 public static void setDnsResolverSampleRanges(@NonNull Context context,
490 @NonNull Range<Integer> range) {
491 if (range.getLower() < 0 || range.getUpper() > 64) {
492 throw new IllegalArgumentException("Argument must be 0~64");
493 }
494 Settings.Global.putInt(
495 context.getContentResolver(), DNS_RESOLVER_MIN_SAMPLES, range.getLower());
496 Settings.Global.putInt(
497 context.getContentResolver(), DNS_RESOLVER_MAX_SAMPLES, range.getUpper());
498 }
499
500 /**
501 * Get maximum count (from {@link Settings}) of switching network notifications shown in 24
502 * hours.
503 *
504 * @param context The {@link Context} to query the setting.
505 * @param def The default value if no setting value.
506 * @return The maximum count of notifications shown in 24 hours when switching networks.
507 */
508 public static int getNetworkSwitchNotificationMaximumDailyCount(@NonNull Context context,
509 int def) {
510 return Settings.Global.getInt(
511 context.getContentResolver(), NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, def);
512 }
513
514 /**
515 * Set maximum count (to {@link Settings}) of switching network notifications shown in 24 hours.
516 * The count must be at least 0.
517 *
518 * @param context The {@link Context} to set the setting.
519 * @param count The maximum count of switching network notifications shown in 24 hours.
520 */
521 public static void setNetworkSwitchNotificationMaximumDailyCount(@NonNull Context context,
522 @IntRange(from = 0) int count) {
523 if (count < 0) {
524 throw new IllegalArgumentException("Count must be 0~10.");
525 }
526 Settings.Global.putInt(
527 context.getContentResolver(), NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT, count);
528 }
529
530 /**
531 * Get minimum duration (from {@link Settings}) between each switching network notifications.
532 *
533 * @param context The {@link Context} to query the setting.
534 * @param def The default time if no setting value.
535 * @return The minimum duration between notifications when switching networks.
536 */
537 @NonNull
538 public static Duration getNetworkSwitchNotificationRateDuration(@NonNull Context context,
539 @NonNull Duration def) {
540 final int duration = Settings.Global.getInt(context.getContentResolver(),
541 NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, (int) def.toMillis());
542 return Duration.ofMillis(duration);
543 }
544
545 /**
546 * Set minimum duration (to {@link Settings}) between each switching network notifications.
547 *
548 * @param context The {@link Context} to set the setting.
549 * @param duration The minimum duration between notifications when switching networks.
550 */
551 public static void setNetworkSwitchNotificationRateDuration(@NonNull Context context,
552 @NonNull Duration duration) {
553 final int time = (int) duration.toMillis();
554 if (time < 0) {
555 throw new IllegalArgumentException("Invalid duration.");
556 }
557 Settings.Global.putInt(context.getContentResolver(),
558 NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS, time);
559 }
560
561 /**
562 * Get URL (from {@link Settings}) used for HTTP captive portal detection upon a new connection.
563 *
564 * @param context The {@link Context} to query the setting.
565 * @return The URL used for HTTP captive portal detection upon a new connection.
566 */
567 @Nullable
568 public static String getCaptivePortalHttpUrl(@NonNull Context context) {
569 return Settings.Global.getString(context.getContentResolver(), CAPTIVE_PORTAL_HTTP_URL);
570 }
571
572 /**
573 * Set URL (to {@link Settings}) used for HTTP captive portal detection upon a new connection.
574 * This URL should respond with a 204 response to a GET request to indicate no captive portal is
575 * present. And this URL must be HTTP as redirect responses are used to find captive portal
576 * sign-in pages. If the URL set to null or be incorrect, it will result in captive portal
577 * detection failed and lost the connection.
578 *
579 * @param context The {@link Context} to set the setting.
580 * @param url The URL used for HTTP captive portal detection upon a new connection.
581 */
582 public static void setCaptivePortalHttpUrl(@NonNull Context context, @Nullable String url) {
583 Settings.Global.putString(context.getContentResolver(), CAPTIVE_PORTAL_HTTP_URL, url);
584 }
585
586 /**
587 * Get mode (from {@link Settings}) when connecting a network that presents a captive portal.
588 *
589 * @param context The {@link Context} to query the setting.
590 * @param def The default mode if no setting value.
591 * @return The mode when connecting a network that presents a captive portal.
592 */
593 @CaptivePortalMode
594 public static int getCaptivePortalMode(@NonNull Context context,
595 @CaptivePortalMode int def) {
596 return Settings.Global.getInt(context.getContentResolver(), CAPTIVE_PORTAL_MODE, def);
597 }
598
599 /**
600 * Set mode (to {@link Settings}) when connecting a network that presents a captive portal.
601 *
602 * @param context The {@link Context} to set the setting.
603 * @param mode The mode when connecting a network that presents a captive portal.
604 */
605 public static void setCaptivePortalMode(@NonNull Context context, @CaptivePortalMode int mode) {
606 if (!(mode == CAPTIVE_PORTAL_MODE_IGNORE
607 || mode == CAPTIVE_PORTAL_MODE_PROMPT
608 || mode == CAPTIVE_PORTAL_MODE_AVOID)) {
609 throw new IllegalArgumentException("Invalid captive portal mode");
610 }
611 Settings.Global.putInt(context.getContentResolver(), CAPTIVE_PORTAL_MODE, mode);
612 }
613
614 /**
615 * Get the global HTTP proxy applied to the device, or null if none.
616 *
617 * @param context The {@link Context} to query the setting.
618 * @return The {@link ProxyInfo} which build from global http proxy settings.
619 */
620 @Nullable
621 public static ProxyInfo getGlobalProxy(@NonNull Context context) {
622 final String host = Settings.Global.getString(
623 context.getContentResolver(), GLOBAL_HTTP_PROXY_HOST);
624 final int port = Settings.Global.getInt(
625 context.getContentResolver(), GLOBAL_HTTP_PROXY_PORT, 0 /* def */);
626 final String exclusionList = Settings.Global.getString(
627 context.getContentResolver(), GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
628 final String pacFileUrl = Settings.Global.getString(
629 context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC);
630
631 if (TextUtils.isEmpty(host) && TextUtils.isEmpty(pacFileUrl)) {
632 return null; // No global proxy.
633 }
634
635 if (TextUtils.isEmpty(pacFileUrl)) {
636 return ProxyInfo.buildDirectProxy(
637 host, port, ProxyUtils.exclusionStringAsList(exclusionList));
638 } else {
639 return ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl));
640 }
641 }
642
643 /**
644 * Set global http proxy settings from given {@link ProxyInfo}.
645 *
646 * @param context The {@link Context} to set the setting.
647 * @param proxyInfo The {@link ProxyInfo} for global http proxy settings which build from
648 * {@link ProxyInfo#buildPacProxy(Uri)} or
649 * {@link ProxyInfo#buildDirectProxy(String, int, List)}
650 */
651 public static void setGlobalProxy(@NonNull Context context, @NonNull ProxyInfo proxyInfo) {
652 final String host = proxyInfo.getHost();
653 final int port = proxyInfo.getPort();
654 final String exclusionList = proxyInfo.getExclusionListAsString();
655 final String pacFileUrl = proxyInfo.getPacFileUrl().toString();
656
657 if (TextUtils.isEmpty(pacFileUrl)) {
658 Settings.Global.putString(context.getContentResolver(), GLOBAL_HTTP_PROXY_HOST, host);
659 Settings.Global.putInt(context.getContentResolver(), GLOBAL_HTTP_PROXY_PORT, port);
660 Settings.Global.putString(
661 context.getContentResolver(), GLOBAL_HTTP_PROXY_EXCLUSION_LIST, exclusionList);
662 Settings.Global.putString(
663 context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, "" /* value */);
664 } else {
665 Settings.Global.putString(
666 context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
667 Settings.Global.putString(
668 context.getContentResolver(), GLOBAL_HTTP_PROXY_HOST, "" /* value */);
669 Settings.Global.putInt(
670 context.getContentResolver(), GLOBAL_HTTP_PROXY_PORT, 0 /* value */);
671 Settings.Global.putString(
672 context.getContentResolver(), GLOBAL_HTTP_PROXY_EXCLUSION_LIST, "" /* value */);
673 }
674 }
675
676 /**
677 * Clear all global http proxy settings.
678 *
679 * @param context The {@link Context} to set the setting.
680 */
681 public static void clearGlobalProxy(@NonNull Context context) {
682 Settings.Global.putString(
683 context.getContentResolver(), GLOBAL_HTTP_PROXY_HOST, "" /* value */);
684 Settings.Global.putInt(
685 context.getContentResolver(), GLOBAL_HTTP_PROXY_PORT, 0 /* value */);
686 Settings.Global.putString(
687 context.getContentResolver(), GLOBAL_HTTP_PROXY_EXCLUSION_LIST, "" /* value */);
688 Settings.Global.putString(
689 context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, "" /* value */);
690 }
691
692 /**
693 * Get specific private dns provider name from {@link Settings}.
694 *
695 * @param context The {@link Context} to query the setting.
696 * @return The specific private dns provider name, or null if no setting value.
697 */
698 @Nullable
699 public static String getPrivateDnsHostname(@NonNull Context context) {
700 return Settings.Global.getString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER);
701 }
702
703 /**
704 * Set specific private dns provider name to {@link Settings}.
705 *
706 * @param context The {@link Context} to set the setting.
707 * @param specifier The specific private dns provider name.
708 */
709 public static void setPrivateDnsHostname(@NonNull Context context,
710 @Nullable String specifier) {
711 Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER, specifier);
712 }
713
714 /**
715 * Get default private dns mode from {@link Settings}.
716 *
717 * @param context The {@link Context} to query the setting.
718 * @return The default private dns mode.
719 */
720 @PrivateDnsMode
721 @NonNull
722 public static String getPrivateDnsDefaultMode(@NonNull Context context) {
723 return Settings.Global.getString(context.getContentResolver(), PRIVATE_DNS_DEFAULT_MODE);
724 }
725
726 /**
727 * Set default private dns mode to {@link Settings}.
728 *
729 * @param context The {@link Context} to set the setting.
730 * @param mode The default private dns mode. This should be one of the PRIVATE_DNS_MODE_*
731 * constants.
732 */
733 public static void setPrivateDnsDefaultMode(@NonNull Context context,
734 @NonNull @PrivateDnsMode String mode) {
735 if (!(mode == PRIVATE_DNS_MODE_OFF
736 || mode == PRIVATE_DNS_MODE_OPPORTUNISTIC
737 || mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
738 throw new IllegalArgumentException("Invalid private dns mode");
739 }
740 Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_DEFAULT_MODE, mode);
741 }
742
743 /**
744 * Get duration (from {@link Settings}) to keep a PendingIntent-based request.
745 *
746 * @param context The {@link Context} to query the setting.
747 * @param def The default duration if no setting value.
748 * @return The duration to keep a PendingIntent-based request.
749 */
750 @NonNull
751 public static Duration getConnectivityKeepPendingIntentDuration(@NonNull Context context,
752 @NonNull Duration def) {
753 final int duration = Settings.Secure.getInt(context.getContentResolver(),
754 CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, (int) def.toMillis());
755 return Duration.ofMillis(duration);
756 }
757
758 /**
759 * Set duration (to {@link Settings}) to keep a PendingIntent-based request.
760 *
761 * @param context The {@link Context} to set the setting.
762 * @param duration The duration to keep a PendingIntent-based request.
763 */
764 public static void setConnectivityKeepPendingIntentDuration(@NonNull Context context,
765 @NonNull Duration duration) {
766 final int time = (int) duration.toMillis();
767 if (time < 0) {
768 throw new IllegalArgumentException("Invalid duration.");
769 }
770 Settings.Secure.putInt(
771 context.getContentResolver(), CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, time);
772 }
773
774 /**
775 * Read from {@link Settings} whether the mobile data connection should remain active
776 * even when higher priority networks are active.
777 *
778 * @param context The {@link Context} to query the setting.
779 * @param def The default value if no setting value.
780 * @return Whether the mobile data connection should remain active even when higher
781 * priority networks are active.
782 */
783 public static boolean getMobileDataAlwaysOn(@NonNull Context context, boolean def) {
784 final int enable = Settings.Global.getInt(
785 context.getContentResolver(), MOBILE_DATA_ALWAYS_ON, (def ? 1 : 0));
786 return (enable != 0) ? true : false;
787 }
788
789 /**
790 * Write into {@link Settings} whether the mobile data connection should remain active
791 * even when higher priority networks are active.
792 *
793 * @param context The {@link Context} to set the setting.
794 * @param enable Whether the mobile data connection should remain active even when higher
795 * priority networks are active.
796 */
797 public static void setMobileDataAlwaysOn(@NonNull Context context, boolean enable) {
798 Settings.Global.putInt(
799 context.getContentResolver(), MOBILE_DATA_ALWAYS_ON, (enable ? 1 : 0));
800 }
801
802 /**
803 * Read from {@link Settings} whether the wifi data connection should remain active
804 * even when higher priority networks are active.
805 *
806 * @param context The {@link Context} to query the setting.
807 * @param def The default value if no setting value.
808 * @return Whether the wifi data connection should remain active even when higher
809 * priority networks are active.
810 */
811 public static boolean getWifiAlwaysRequested(@NonNull Context context, boolean def) {
812 final int enable = Settings.Global.getInt(
813 context.getContentResolver(), WIFI_ALWAYS_REQUESTED, (def ? 1 : 0));
814 return (enable != 0) ? true : false;
815 }
816
817 /**
818 * Write into {@link Settings} whether the wifi data connection should remain active
819 * even when higher priority networks are active.
820 *
821 * @param context The {@link Context} to set the setting.
822 * @param enable Whether the wifi data connection should remain active even when higher
823 * priority networks are active
824 */
825 public static void setWifiAlwaysRequested(@NonNull Context context, boolean enable) {
826 Settings.Global.putInt(
827 context.getContentResolver(), WIFI_ALWAYS_REQUESTED, (enable ? 1 : 0));
828 }
829
830 /**
831 * Get avoid bad wifi setting from {@link Settings}.
832 *
833 * @param context The {@link Context} to query the setting.
834 * @return The setting whether to automatically switch away from wifi networks that lose
835 * internet access.
836 */
837 @NetworkAvoidBadWifi
838 public static int getNetworkAvoidBadWifi(@NonNull Context context) {
839 final String setting =
840 Settings.Global.getString(context.getContentResolver(), NETWORK_AVOID_BAD_WIFI);
841 if ("0".equals(setting)) {
842 return NETWORK_AVOID_BAD_WIFI_IGNORE;
843 } else if ("1".equals(setting)) {
844 return NETWORK_AVOID_BAD_WIFI_AVOID;
845 } else {
846 return NETWORK_AVOID_BAD_WIFI_PROMPT;
847 }
848 }
849
850 /**
851 * Set avoid bad wifi setting to {@link Settings}.
852 *
853 * @param context The {@link Context} to set the setting.
854 * @param value Whether to automatically switch away from wifi networks that lose internet
855 * access.
856 */
857 public static void setNetworkAvoidBadWifi(@NonNull Context context,
858 @NetworkAvoidBadWifi int value) {
859 final String setting;
860 if (value == NETWORK_AVOID_BAD_WIFI_IGNORE) {
861 setting = "0";
862 } else if (value == NETWORK_AVOID_BAD_WIFI_AVOID) {
863 setting = "1";
864 } else if (value == NETWORK_AVOID_BAD_WIFI_PROMPT) {
865 setting = null;
866 } else {
867 throw new IllegalArgumentException("Invalid avoid bad wifi setting");
868 }
869 Settings.Global.putString(context.getContentResolver(), NETWORK_AVOID_BAD_WIFI, setting);
870 }
871
872 /**
873 * Get network metered multipath preference from {@link Settings}.
874 *
875 * @param context The {@link Context} to query the setting.
876 * @return The network metered multipath preference which should be one of
877 * ConnectivityManager#MULTIPATH_PREFERENCE_* value or null if the value specified
878 * by config_networkMeteredMultipathPreference is used.
879 */
880 @Nullable
881 public static String getNetworkMeteredMultipathPreference(@NonNull Context context) {
882 return Settings.Global.getString(
883 context.getContentResolver(), NETWORK_METERED_MULTIPATH_PREFERENCE);
884 }
885
886 /**
887 * Set network metered multipath preference to {@link Settings}.
888 *
889 * @param context The {@link Context} to set the setting.
890 * @param preference The network metered multipath preference which should be one of
891 * ConnectivityManager#MULTIPATH_PREFERENCE_* value or null if the value
892 * specified by config_networkMeteredMultipathPreference is used.
893 */
894 public static void setNetworkMeteredMultipathPreference(@NonNull Context context,
895 @NonNull @MultipathPreference String preference) {
896 if (!(Integer.valueOf(preference) == MULTIPATH_PREFERENCE_HANDOVER
897 || Integer.valueOf(preference) == MULTIPATH_PREFERENCE_RELIABILITY
898 || Integer.valueOf(preference) == MULTIPATH_PREFERENCE_PERFORMANCE)) {
899 throw new IllegalArgumentException("Invalid private dns mode");
900 }
901 Settings.Global.putString(
902 context.getContentResolver(), NETWORK_METERED_MULTIPATH_PREFERENCE, preference);
903 }
paulhu7a4eeed2021-03-25 13:17:58 +0800904
905 /**
906 * Get the list of apps(from {@link Settings}) that should go on cellular networks in preference
907 * even when higher-priority networks are connected.
908 *
909 * @param context The {@link Context} to query the setting.
910 * @return A list of apps that should go on cellular networks in preference even when
911 * higher-priority networks are connected or null if no setting value.
912 */
913 @Nullable
914 public static String getMobileDataPreferredApps(@NonNull Context context) {
915 return Settings.Secure.getString(context.getContentResolver(), MOBILE_DATA_PREFERRED_APPS);
916 }
917
918 /**
919 * Set the list of apps(to {@link Settings}) that should go on cellular networks in preference
920 * even when higher-priority networks are connected.
921 *
922 * @param context The {@link Context} to set the setting.
923 * @param list A list of apps that should go on cellular networks in preference even when
924 * higher-priority networks are connected.
925 */
926 public static void setMobileDataPreferredApps(@NonNull Context context, @Nullable String list) {
927 Settings.Secure.putString(context.getContentResolver(), MOBILE_DATA_PREFERRED_APPS, list);
928 }
paulhu845456e2021-03-17 17:19:09 +0800929}