1 /*
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 
17 package com.android.net.module.util;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.ContentResolver;
22 import android.content.Context;
23 import android.provider.Settings;
24 import android.text.TextUtils;
25 
26 /**
27  * Collection of connectivity settings utilities.
28  *
29  * @hide
30  */
31 public class ConnectivitySettingsUtils {
32     public static final int PRIVATE_DNS_MODE_OFF = 1;
33     public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2;
34     public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3;
35 
36     public static final String PRIVATE_DNS_DEFAULT_MODE = "private_dns_default_mode";
37     public static final String PRIVATE_DNS_MODE = "private_dns_mode";
38     public static final String PRIVATE_DNS_MODE_OFF_STRING = "off";
39     public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING = "opportunistic";
40     public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING = "hostname";
41     public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier";
42 
43     /**
44      * Get private DNS mode as string.
45      *
46      * @param mode One of the private DNS values.
47      * @return A string of private DNS mode.
48      */
getPrivateDnsModeAsString(int mode)49     public static String getPrivateDnsModeAsString(int mode) {
50         switch (mode) {
51             case PRIVATE_DNS_MODE_OFF:
52                 return PRIVATE_DNS_MODE_OFF_STRING;
53             case PRIVATE_DNS_MODE_OPPORTUNISTIC:
54                 return PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING;
55             case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
56                 return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING;
57             default:
58                 throw new IllegalArgumentException("Invalid private dns mode: " + mode);
59         }
60     }
61 
getPrivateDnsModeAsInt(String mode)62     private static int getPrivateDnsModeAsInt(String mode) {
63         // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose
64         // PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode.
65         if (TextUtils.isEmpty(mode))
66             return PRIVATE_DNS_MODE_OPPORTUNISTIC;
67         switch (mode) {
68             case "off":
69                 return PRIVATE_DNS_MODE_OFF;
70             case "hostname":
71                 return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
72             case "opportunistic":
73                 return PRIVATE_DNS_MODE_OPPORTUNISTIC;
74             default:
75                 // b/260211513: adb shell settings put global private_dns_mode foo
76                 // can result in arbitrary strings - treat any unknown value as empty string.
77                 // throw new IllegalArgumentException("Invalid private dns mode: " + mode);
78                 return PRIVATE_DNS_MODE_OPPORTUNISTIC;
79         }
80     }
81 
82     /**
83      * Get private DNS mode from settings.
84      *
85      * @param context The Context to query the private DNS mode from settings.
86      * @return An integer of private DNS mode.
87      */
getPrivateDnsMode(@onNull Context context)88     public static int getPrivateDnsMode(@NonNull Context context) {
89         final ContentResolver cr = context.getContentResolver();
90         String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE);
91         if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE);
92         return getPrivateDnsModeAsInt(mode);
93     }
94 
95     /**
96      * Set private DNS mode to settings.
97      *
98      * @param context The {@link Context} to set the private DNS mode.
99      * @param mode The private dns mode. This should be one of the PRIVATE_DNS_MODE_* constants.
100      */
setPrivateDnsMode(@onNull Context context, int mode)101     public static void setPrivateDnsMode(@NonNull Context context, int mode) {
102         if (!(mode == PRIVATE_DNS_MODE_OFF
103                 || mode == PRIVATE_DNS_MODE_OPPORTUNISTIC
104                 || mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
105             throw new IllegalArgumentException("Invalid private dns mode: " + mode);
106         }
107         Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_MODE,
108                 getPrivateDnsModeAsString(mode));
109     }
110 
111     /**
112      * Get specific private dns provider name from {@link Settings}.
113      *
114      * @param context The {@link Context} to query the setting.
115      * @return The specific private dns provider name, or null if no setting value.
116      */
117     @Nullable
getPrivateDnsHostname(@onNull Context context)118     public static String getPrivateDnsHostname(@NonNull Context context) {
119         return Settings.Global.getString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER);
120     }
121 
122     /**
123      * Set specific private dns provider name to {@link Settings}.
124      *
125      * @param context The {@link Context} to set the setting.
126      * @param specifier The specific private dns provider name.
127      */
setPrivateDnsHostname(@onNull Context context, @Nullable String specifier)128     public static void setPrivateDnsHostname(@NonNull Context context, @Nullable String specifier) {
129         Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER, specifier);
130     }
131 }
132