Home | History | Annotate | Download | only in dataconnection
      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
     80     public String toString() {
     81         return "[mInternalDataEnabled=" + mInternalDataEnabled
     82                 + ", isUserDataEnabled=" + isUserDataEnabled()
     83                 + ", isProvisioningDataEnabled=" + isProvisioningDataEnabled()
     84                 + ", mPolicyDataEnabled=" + mPolicyDataEnabled
     85                 + ", mCarrierDataEnabled=" + mCarrierDataEnabled + "]";
     86     }
     87 
     88     public DataEnabledSettings(Phone phone) {
     89         mPhone = phone;
     90         mResolver = mPhone.getContext().getContentResolver();
     91     }
     92 
     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     }
    101     public synchronized boolean isInternalDataEnabled() {
    102         return mInternalDataEnabled;
    103     }
    104 
    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     }
    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 
    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 
    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     }
    143     public synchronized boolean isPolicyDataEnabled() {
    144         return mPolicyDataEnabled;
    145     }
    146 
    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     }
    155     public synchronized boolean isCarrierDataEnabled() {
    156         return mCarrierDataEnabled;
    157     }
    158 
    159     public synchronized boolean isDataEnabled() {
    160         if (isProvisioning()) {
    161             return isProvisioningDataEnabled();
    162         } else {
    163             return mInternalDataEnabled && isUserDataEnabled()
    164                     && mPolicyDataEnabled && mCarrierDataEnabled;
    165         }
    166     }
    167 
    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      */
    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 
    192     private void notifyDataEnabledChanged(boolean enabled, int reason) {
    193         mDataEnabledChangedRegistrants.notifyResult(new Pair<>(enabled, reason));
    194     }
    195 
    196     public void registerForDataEnabledChanged(Handler h, int what, Object obj) {
    197         mDataEnabledChangedRegistrants.addUnique(h, what, obj);
    198         notifyDataEnabledChanged(isDataEnabled(), REASON_REGISTERED);
    199     }
    200 
    201     public void unregisterForDataEnabledChanged(Handler h) {
    202         mDataEnabledChangedRegistrants.remove(h);
    203     }
    204 
    205     private void log(String s) {
    206         Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
    207     }
    208 
    209     private void localLog(String name, boolean value) {
    210         mSettingChangeLocalLog.log(name + " change to " + value);
    211     }
    212 
    213     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    214         pw.println(" DataEnabledSettings=");
    215         mSettingChangeLocalLog.dump(fd, pw, args);
    216     }
    217 }
    218