1 /*
2  * Copyright (C) 2016 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.internal.telephony.dataconnection;
18 
19 
20 import android.content.ContentResolver;
21 import android.os.Handler;
22 import android.os.RegistrantList;
23 import android.os.SystemProperties;
24 import android.provider.Settings;
25 import android.telephony.Rlog;
26 import android.telephony.SubscriptionManager;
27 import android.telephony.TelephonyManager;
28 import android.util.LocalLog;
29 import android.util.Pair;
30 
31 import com.android.internal.telephony.Phone;
32 
33 import java.io.FileDescriptor;
34 import java.io.PrintWriter;
35 
36 /**
37  * The class to hold different data enabled/disabled settings. Also it allows clients to register
38  * for overall data enabled setting changed event.
39  * @hide
40  */
41 public class DataEnabledSettings {
42 
43     private static final String LOG_TAG = "DataEnabledSettings";
44 
45     public static final int REASON_REGISTERED = 0;
46 
47     public static final int REASON_INTERNAL_DATA_ENABLED = 1;
48 
49     public static final int REASON_USER_DATA_ENABLED = 2;
50 
51     public static final int REASON_POLICY_DATA_ENABLED = 3;
52 
53     public static final int REASON_DATA_ENABLED_BY_CARRIER = 4;
54 
55     /**
56      * responds to the setInternalDataEnabled call - used internally to turn off data.
57      * For example during emergency calls
58      */
59     private boolean mInternalDataEnabled = true;
60 
61     /**
62      * Flag indicating data allowed by network policy manager or not.
63      */
64     private boolean mPolicyDataEnabled = true;
65 
66     /**
67      * Indicate if metered APNs are enabled by the carrier. set false to block all the metered APNs
68      * from continuously sending requests, which causes undesired network load.
69      */
70     private boolean mCarrierDataEnabled = true;
71 
72     private Phone mPhone = null;
73     private ContentResolver mResolver = null;
74 
75     private final RegistrantList mDataEnabledChangedRegistrants = new RegistrantList();
76 
77     private final LocalLog mSettingChangeLocalLog = new LocalLog(50);
78 
79     @Override
toString()80     public String toString() {
81         return "[mInternalDataEnabled=" + mInternalDataEnabled
82                 + ", isUserDataEnabled=" + isUserDataEnabled()
83                 + ", isProvisioningDataEnabled=" + isProvisioningDataEnabled()
84                 + ", mPolicyDataEnabled=" + mPolicyDataEnabled
85                 + ", mCarrierDataEnabled=" + mCarrierDataEnabled + "]";
86     }
87 
DataEnabledSettings(Phone phone)88     public DataEnabledSettings(Phone phone) {
89         mPhone = phone;
90         mResolver = mPhone.getContext().getContentResolver();
91     }
92 
setInternalDataEnabled(boolean enabled)93     public synchronized void setInternalDataEnabled(boolean enabled) {
94         localLog("InternalDataEnabled", enabled);
95         boolean prevDataEnabled = isDataEnabled();
96         mInternalDataEnabled = enabled;
97         if (prevDataEnabled != isDataEnabled()) {
98             notifyDataEnabledChanged(!prevDataEnabled, REASON_INTERNAL_DATA_ENABLED);
99         }
100     }
isInternalDataEnabled()101     public synchronized boolean isInternalDataEnabled() {
102         return mInternalDataEnabled;
103     }
104 
setUserDataEnabled(boolean enabled)105     public synchronized void setUserDataEnabled(boolean enabled) {
106         localLog("UserDataEnabled", enabled);
107         boolean prevDataEnabled = isDataEnabled();
108 
109         Settings.Global.putInt(mResolver, getMobileDataSettingName(), enabled ? 1 : 0);
110 
111         if (prevDataEnabled != isDataEnabled()) {
112             notifyDataEnabledChanged(!prevDataEnabled, REASON_USER_DATA_ENABLED);
113         }
114     }
isUserDataEnabled()115     public synchronized boolean isUserDataEnabled() {
116         boolean defaultVal = "true".equalsIgnoreCase(SystemProperties.get(
117                 "ro.com.android.mobiledata", "true"));
118 
119         return (Settings.Global.getInt(mResolver, getMobileDataSettingName(),
120                 defaultVal ? 1 : 0) != 0);
121     }
122 
getMobileDataSettingName()123     private String getMobileDataSettingName() {
124         // For single SIM phones, this is a per phone property. Or if it's invalid subId, we
125         // read default setting.
126         int subId = mPhone.getSubId();
127         if (TelephonyManager.getDefault().getSimCount() == 1
128                 || !SubscriptionManager.isValidSubscriptionId(subId)) {
129             return Settings.Global.MOBILE_DATA;
130         } else {
131             return Settings.Global.MOBILE_DATA + mPhone.getSubId();
132         }
133     }
134 
setPolicyDataEnabled(boolean enabled)135     public synchronized void setPolicyDataEnabled(boolean enabled) {
136         localLog("PolicyDataEnabled", enabled);
137         boolean prevDataEnabled = isDataEnabled();
138         mPolicyDataEnabled = enabled;
139         if (prevDataEnabled != isDataEnabled()) {
140             notifyDataEnabledChanged(!prevDataEnabled, REASON_POLICY_DATA_ENABLED);
141         }
142     }
isPolicyDataEnabled()143     public synchronized boolean isPolicyDataEnabled() {
144         return mPolicyDataEnabled;
145     }
146 
setCarrierDataEnabled(boolean enabled)147     public synchronized void setCarrierDataEnabled(boolean enabled) {
148         localLog("CarrierDataEnabled", enabled);
149         boolean prevDataEnabled = isDataEnabled();
150         mCarrierDataEnabled = enabled;
151         if (prevDataEnabled != isDataEnabled()) {
152             notifyDataEnabledChanged(!prevDataEnabled, REASON_DATA_ENABLED_BY_CARRIER);
153         }
154     }
isCarrierDataEnabled()155     public synchronized boolean isCarrierDataEnabled() {
156         return mCarrierDataEnabled;
157     }
158 
isDataEnabled()159     public synchronized boolean isDataEnabled() {
160         if (isProvisioning()) {
161             return isProvisioningDataEnabled();
162         } else {
163             return mInternalDataEnabled && isUserDataEnabled()
164                     && mPolicyDataEnabled && mCarrierDataEnabled;
165         }
166     }
167 
isProvisioning()168     public boolean isProvisioning() {
169         return Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0;
170     }
171     /**
172      * In provisioning, we might want to have enable mobile data during provisioning. It depends
173      * on value of Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED which is set by
174      * setupwizard. It only matters if it's in provisioning stage.
175      * @return whether we are enabling userData during provisioning stage.
176      */
isProvisioningDataEnabled()177     public boolean isProvisioningDataEnabled() {
178         final String prov_property = SystemProperties.get("ro.com.android.prov_mobiledata",
179                 "false");
180         boolean retVal = "true".equalsIgnoreCase(prov_property);
181 
182         final int prov_mobile_data = Settings.Global.getInt(mResolver,
183                 Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
184                 retVal ? 1 : 0);
185         retVal = prov_mobile_data != 0;
186         log("getDataEnabled during provisioning retVal=" + retVal + " - (" + prov_property
187                 + ", " + prov_mobile_data + ")");
188 
189         return retVal;
190     }
191 
notifyDataEnabledChanged(boolean enabled, int reason)192     private void notifyDataEnabledChanged(boolean enabled, int reason) {
193         mDataEnabledChangedRegistrants.notifyResult(new Pair<>(enabled, reason));
194     }
195 
registerForDataEnabledChanged(Handler h, int what, Object obj)196     public void registerForDataEnabledChanged(Handler h, int what, Object obj) {
197         mDataEnabledChangedRegistrants.addUnique(h, what, obj);
198         notifyDataEnabledChanged(isDataEnabled(), REASON_REGISTERED);
199     }
200 
unregisterForDataEnabledChanged(Handler h)201     public void unregisterForDataEnabledChanged(Handler h) {
202         mDataEnabledChangedRegistrants.remove(h);
203     }
204 
log(String s)205     private void log(String s) {
206         Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
207     }
208 
localLog(String name, boolean value)209     private void localLog(String name, boolean value) {
210         mSettingChangeLocalLog.log(name + " change to " + value);
211     }
212 
dump(FileDescriptor fd, PrintWriter pw, String[] args)213     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
214         pw.println(" DataEnabledSettings=");
215         mSettingChangeLocalLog.dump(fd, pw, args);
216     }
217 }
218