1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.settings.datausage; 16 17 import static android.net.ConnectivityManager.TYPE_MOBILE; 18 import static android.net.ConnectivityManager.TYPE_WIFI; 19 import static android.telephony.TelephonyManager.SIM_STATE_READY; 20 21 import android.app.usage.NetworkStats.Bucket; 22 import android.app.usage.NetworkStatsManager; 23 import android.content.Context; 24 import android.net.ConnectivityManager; 25 import android.net.NetworkTemplate; 26 import android.os.RemoteException; 27 import android.os.SystemProperties; 28 import android.telephony.SubscriptionInfo; 29 import android.telephony.SubscriptionManager; 30 import android.telephony.TelephonyManager; 31 import android.text.BidiFormatter; 32 import android.text.format.Formatter; 33 import android.text.format.Formatter.BytesResult; 34 import android.util.Log; 35 36 import java.util.ArrayList; 37 import java.util.List; 38 39 /** 40 * Utility methods for data usage classes. 41 */ 42 public final class DataUsageUtils extends com.android.settingslib.net.DataUsageUtils { 43 static final boolean TEST_RADIOS = false; 44 static final String TEST_RADIOS_PROP = "test.radios"; 45 private static final boolean LOGD = false; 46 private static final String ETHERNET = "ethernet"; 47 private static final String TAG = "DataUsageUtils"; 48 DataUsageUtils()49 private DataUsageUtils() { 50 } 51 52 /** 53 * Format byte value to readable string using IEC units. 54 */ formatDataUsage(Context context, long byteValue)55 public static CharSequence formatDataUsage(Context context, long byteValue) { 56 final BytesResult res = Formatter.formatBytes(context.getResources(), byteValue, 57 Formatter.FLAG_IEC_UNITS); 58 return BidiFormatter.getInstance().unicodeWrap(context.getString( 59 com.android.internal.R.string.fileSizeSuffix, res.value, res.units)); 60 } 61 62 /** 63 * Test if device has an ethernet network connection. 64 */ hasEthernet(Context context)65 public static boolean hasEthernet(Context context) { 66 if (DataUsageUtils.TEST_RADIOS) { 67 return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains(ETHERNET); 68 } 69 70 final ConnectivityManager conn = ConnectivityManager.from(context); 71 if (!conn.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET)) { 72 return false; 73 } 74 75 final TelephonyManager telephonyManager = TelephonyManager.from(context); 76 final NetworkStatsManager networkStatsManager = 77 context.getSystemService(NetworkStatsManager.class); 78 boolean hasEthernetUsage = false; 79 try { 80 final Bucket bucket = networkStatsManager.querySummaryForUser( 81 ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(), 82 0L /* startTime */, System.currentTimeMillis() /* endTime */); 83 if (bucket != null) { 84 hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0; 85 } 86 } catch (RemoteException e) { 87 Log.e(TAG, "Exception querying network detail.", e); 88 } 89 return hasEthernetUsage; 90 } 91 92 /** 93 * Returns whether device has mobile data. 94 * TODO: This is the opposite to Utils.isWifiOnly(), it should be refactored into 1 method. 95 */ hasMobileData(Context context)96 public static boolean hasMobileData(Context context) { 97 ConnectivityManager connectivityManager = ConnectivityManager.from(context); 98 return connectivityManager != null && connectivityManager 99 .isNetworkSupported(ConnectivityManager.TYPE_MOBILE); 100 } 101 102 /** 103 * Test if device has a mobile data radio with SIM in ready state. 104 */ hasReadyMobileRadio(Context context)105 public static boolean hasReadyMobileRadio(Context context) { 106 if (DataUsageUtils.TEST_RADIOS) { 107 return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains("mobile"); 108 } 109 final List<SubscriptionInfo> subInfoList = 110 SubscriptionManager.from(context).getActiveSubscriptionInfoList(true); 111 // No activated Subscriptions 112 if (subInfoList == null) { 113 if (LOGD) { 114 Log.d(TAG, "hasReadyMobileRadio: subInfoList=null"); 115 } 116 return false; 117 } 118 final TelephonyManager tele = TelephonyManager.from(context); 119 // require both supported network and ready SIM 120 boolean isReady = true; 121 for (SubscriptionInfo subInfo : subInfoList) { 122 isReady = isReady & tele.getSimState(subInfo.getSimSlotIndex()) == SIM_STATE_READY; 123 if (LOGD) { 124 Log.d(TAG, "hasReadyMobileRadio: subInfo=" + subInfo); 125 } 126 } 127 final ConnectivityManager conn = ConnectivityManager.from(context); 128 final boolean retVal = conn.isNetworkSupported(TYPE_MOBILE) && isReady; 129 if (LOGD) { 130 Log.d(TAG, "hasReadyMobileRadio:" 131 + " conn.isNetworkSupported(TYPE_MOBILE)=" 132 + conn.isNetworkSupported(TYPE_MOBILE) 133 + " isReady=" + isReady); 134 } 135 return retVal; 136 } 137 138 /** 139 * Whether device has a Wi-Fi data radio. 140 */ hasWifiRadio(Context context)141 public static boolean hasWifiRadio(Context context) { 142 if (TEST_RADIOS) { 143 return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi"); 144 } 145 146 final ConnectivityManager connectivityManager = ConnectivityManager.from(context); 147 return connectivityManager != null && connectivityManager.isNetworkSupported(TYPE_WIFI); 148 } 149 hasSim(Context context)150 public static boolean hasSim(Context context) { 151 TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 152 final int simState = telephonyManager.getSimState(); 153 // Note that pulling the SIM card returns UNKNOWN, not ABSENT. 154 return simState != TelephonyManager.SIM_STATE_ABSENT 155 && simState != TelephonyManager.SIM_STATE_UNKNOWN; 156 } 157 158 /** 159 * Returns the default subscription if available else returns 160 * SubscriptionManager#INVALID_SUBSCRIPTION_ID 161 */ getDefaultSubscriptionId(Context context)162 public static int getDefaultSubscriptionId(Context context) { 163 SubscriptionManager subManager = SubscriptionManager.from(context); 164 if (subManager == null) { 165 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 166 } 167 SubscriptionInfo subscriptionInfo = subManager.getDefaultDataSubscriptionInfo(); 168 if (subscriptionInfo == null) { 169 List<SubscriptionInfo> list = subManager.getAllSubscriptionInfoList(); 170 if (list.size() == 0) { 171 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 172 } 173 subscriptionInfo = list.get(0); 174 } 175 return subscriptionInfo.getSubscriptionId(); 176 } 177 178 /** 179 * Returns the default network template based on the availability of mobile data, Wifi. Returns 180 * ethernet template if both mobile data and Wifi are not available. 181 */ getDefaultTemplate(Context context, int defaultSubId)182 public static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) { 183 if (hasMobileData(context) && defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 184 return getMobileTemplate(context, defaultSubId); 185 } else if (hasWifiRadio(context)) { 186 return NetworkTemplate.buildTemplateWifiWildcard(); 187 } else { 188 return NetworkTemplate.buildTemplateEthernet(); 189 } 190 } 191 192 } 193